skip to Main Content

I’m building an app that contains iOS 14 widgets. User can change widget content by pressing on Edit Widget, and selecting it from provided intent collection. For INObjectCollection I’m using an array of INObject and for each object I’m setting an image this way:

    let image = INImage(url: imageRemoteURL, width: 80, height: 80)
    let myObject = MyCustomObject(identifier: "an id", display: "some text", subtitle: nil, image: image)
    // MyCustomObject is a subclass of INObject

In the list images are displayed properly, but after selecting an item and opening again the view by pressing on Edit Widget – image is shown all system blue, also big sized. See attached screenshot:

enter image description here

I could find only this topic on the issue but with no solution yet.

If I would use an image from app bundle, then a solution would be to set Original for Render As, but no idea how to fix this when using a remote image URL.
Another problem is image size, which is too large.
Any help would be appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to Edward's hints I managed to fix my issues this way:

    func getIntentImage(imageLink: String) -> INImage?
    {
        guard let url = URL(string: imageLink),
              let imageData = try? Data(contentsOf: url),   // may use image local caching
              var image = UIImage(data: imageData) else
        {
            return nil
        }
        let maxSize: CGFloat = 80
        let size = CGSize(width: maxSize, height: maxSize)
        if let resizedImage = image.resizeImage(targetSize: size)
        {
            image = resizedImage
        }
        return INImage(uiImage: image.withRenderingMode(.alwaysOriginal))
    }
    
    // Image resizer:
    extension UIImage
    {
        func resizeImage(targetSize: CGSize) -> UIImage?
        {
            let size = self.size
            
            let widthRatio = targetSize.width / size.width
            let heightRatio = targetSize.height / size.height
            
            // Figure out what our orientation is, and use that to form the rectangle
            var newSize: CGSize
            if widthRatio > heightRatio
            {
                newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
            }
            else
            {
                newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
            }
            
            // This is the rect that we've calculated out and this is what is actually used below
            let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
            
            // Actually do the resizing to the rect using the ImageContext stuff
            UIGraphicsBeginImageContextWithOptions(newSize, false, 1)
            self.draw(in: rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            return newImage
        }
    }
    

  2. 1. Image Size

    I had the same issue with INImage’s size in intent and found out this https://developer.apple.com/documentation/sirikit/inimage/1648800-imagesize but couldn’t find anything about how to use it properly so eventually decided on removing the intent image at all. Maybe it helps you!

    2. Blue Tint

    You can change the image’s default rendering type in your asset catalog or programmatically, and this should remove tint color.

    – Asset Catalog

    Click on the image you want to change in your asset catalog, then go to the Attributes Inspector, and change the "Render As" attribute to "Original Image".

    – Programmatically

    INImage itself actually has a way to set rendering mode, but it is set as private and using this API could get your application rejected by Apple. So, if you’re planning to release it on App Store keep this in mind.

    The "legal" solution is to use INImage(uiImage:) and set the rendering mode on the UIImage.

    var renderedImage: UIImage? = UIImage(named:"myImage")?.withRenderingMode(.alwaysOriginal)
    
    let image = INImage(uiImage: renderedImage, width: 40, height: 40)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search