来自小部件意图集合的 INImage 使用默认蓝色着色

INImage from widgets intent collection is tinted with default blue color

我正在构建一个包含 iOS 14 个小部件的应用程序。用户可以通过按 编辑小部件 并从提供的意图集合中选择它来更改小部件内容。对于 INObjectCollection,我使用的是 INObject 数组,对于每个对象,我都这样设置图像:

    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

在列表中图像显示正确,但在选择一个项目并通过按 编辑小部件 再次打开视图后 - 图像显示为全系统蓝色,尺寸也很大。请参阅随附的屏幕截图:

我只能找到 this 个关于这个问题的主题,但还没有解决方案。

如果我要使用应用程序包中的图像,那么解决方案是为 Render As 设置 Original,但不知道使用远程图像时如何解决此问题 URL。 另一个问题是图像尺寸太大。 任何帮助将不胜感激。

1。图片大小

我对 INImage 的意图大小有同样的问题并发现了这个 https://developer.apple.com/documentation/sirikit/inimage/1648800-imagesize 但找不到任何关于如何正确使用它的信息所以最终决定完全删除意图图像。也许对你有帮助!

2。蓝色色调

您可以在资产目录中或以编程方式更改图像的默认呈现类型,这应该会删除色调。

- 资产目录

在资产目录中单击要更改的图像,然后转到属性检查器,将“渲染为”属性更改为“原始图像”。

– 以编程方式

INImage 本身实际上有一种设置渲染模式的方法,但它被设置为私有并且使用此 API 可能会使您的应用程序被 Apple 拒绝。所以,如果您打算在 App Store 上发布它,请记住这一点。

“合法”的解决方案是使用 INImage(uiImage:) 并在 UIImage 上设置渲染模式。

var renderedImage: UIImage? = UIImage(named:"myImage")?.withRenderingMode(.alwaysOriginal)

let image = INImage(uiImage: renderedImage, width: 40, height: 40)

感谢 Edward 的提示,我设法以这种方式解决了我的问题:

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
    }
}