【问题标题】:How to download images async for WidgetKit如何为 WidgetKit 异步下载图像
【发布时间】:2020-11-20 05:50:41
【问题描述】:

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

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

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

任何建议都会非常有帮助,

【问题讨论】:

    标签: ios swiftui urlsession widgetkit


    【解决方案1】:

    我没有很好的解决方案,但我尝试使用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()

    【讨论】:

      【解决方案2】:

      是的,您应该在时间线提供程序中下载图像并在完成后发送时间线。请参阅 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:) 初始化程序来显示图像

      【讨论】:

      • 这是目前最好的解决方案。我在我的小部件中使用了 SDWebImage,这种技术在 iOS、iPadOS 和 macOS (Catalyst) 上可靠地工作(主机应用程序,小部件将是本机的)
      • 我们应该在 "getTimeline(for configuration..." 中使用它吗?当在其中调用 completion(timeline) 时!?
      • @Ahmadreza 是的,我就是这样使用它的。
      • @dezinezync 您的意思是“在返回时间线之前加载图像”是目前最好的解决方案?因为如果您在小部件视图中使用SDWebImageWebImage,它将在视图正确渲染时加载图像?
      • @fruitcoder 是的。因此,通过在时间线方法中调用它,您实际上是在预热 SDWebImage 缓存,因此当渲染器请求它时,它要么立即可用,要么在加载失败的情况下不可用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多