如何为 WidgetKit 异步下载图像

How to download images async for WidgetKit

我正在为 iOS 开发小部件,我真的不知道如何为小部件下载图像。

小部件当前下载一组对象,每个对象都有一个 URL 图像。这个想法是每个对象都为 Timeline.

创建一个 SimpleEntry

实现此目标的最佳方法是什么?我读到 Widgets 不应该使用 ObservableObject。我在时间轴提供程序中获取对象集,这似乎是 Apple 推荐的。但是我是否也在那里下载图像并等到所有完成后才发送时间线?

任何建议都会很有帮助,

我没有很好的解决方案,但我尝试使用 WidgetCenter.shared.reloadAllTimelines(),它很有意义。 在下面的代码中。

var downloadImage: UIImage?

func downloadImage(url: URL) -> UIImage {
    
    var picImage: UIImage!
    
    if self.downloadImage == nil {
        
        picImage = UIImage(named: "Default Image")
        
        DispatchQueue.global(qos: .background).async {
            do {
                let data = try Data(contentsOf: url)
                DispatchQueue.main.async {
                    self.downloadImage = UIImage.init(data: data)
                    if self.downloadImage != nil {
                        DispatchQueue.main.async {
                            WidgetCenter.shared.reloadAllTimelines()
                        }
                    }
                }
            } catch { }
        }
    } else {
        picImage = self.downloadImage
    }
    
    return picImage
}

还有你要考虑什么时候删除这张图片。 这就像 tableView.reloadData().

是的,您应该在时间线提供程序中下载图像,并在完成后发送时间线。请参阅 Apple 框架工程师的以下 recommendation

我使用调度组来实现这一点。 类似于:

let imageRequestGroup = DispatchGroup()
var images: [UIImage] = []
for imageUrl in imageUrls {
    imageRequestGroup.enter()
    yourAsyncUIImageProvider.getImage(fromUrl: imageUrl) { image in
        images.append(image)
        imageRequestGroup.leave()
    }
}
imageRequestGroup.notify(queue: .main) {
    completion(images)
}

然后我使用 SwiftUI 的 Image(uiImage:) 初始化程序来显示图像