Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/117.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从集合视图内的url下载图像时,哪种方式的性能更好?_Ios_Swift_Multithreading - Fatal编程技术网

Ios 从集合视图内的url下载图像时,哪种方式的性能更好?

Ios 从集合视图内的url下载图像时,哪种方式的性能更好?,ios,swift,multithreading,Ios,Swift,Multithreading,从collectionview内部的url下载图像时,哪种方式的性能更好 比如说 可以通过多种方式从服务器url下载图像,哪种方式更好: 1使用qos=utility创建全局调度并发队列。然后以异步方式执行下载代码 private func donwnloadwithGlobalQueue(at indexpath : IndexPath){ DispatchQueue.global(qos: .utility).async { [weak self] in guard le

从collectionview内部的url下载图像时,哪种方式的性能更好

比如说 可以通过多种方式从服务器url下载图像,哪种方式更好: 1使用qos=utility创建全局调度并发队列。然后以异步方式执行下载代码

private func donwnloadwithGlobalQueue(at indexpath : IndexPath){
    DispatchQueue.global(qos: .utility).async { [weak self] in
      guard let weakself = self else{
        return
      }
      let url = weakself.urls[indexpath.item]

      guard let data = try? Data(contentsOf: url),
        let image = UIImage(data: data) else{
          return
      }
      DispatchQueue.main.async {
        if let cell = self?.collectionView.cellForItem(at: indexpath) as? PhotoCell {
          cell.display(image: image)
        }
      }
    }

  }
2使用NSURLSION数据任务方法

private func downloadwithURLSession(at indexpath : IndexPath){
    URLSession.shared.dataTask(with: urls[indexpath.row]) { [weak self]  (data, response, error) in
      guard let weakself = self,
      let data = data,
      let image = UIImage(data: data) else{
          return
      }

      DispatchQueue.main.async {
        if let cell = weakself.collectionView.cellForItem(at: indexpath) as? PhotoCell {
          cell.display(image: image)
        }
      }
    }.resume()
  }

两者都是相同的,因为它们是后台线程的变体,您最好使用它将您的逻辑封装在缓存中,并在任何时候加载一个映像,因为当用户在加载映像之前来回滚动时会发生这种情况。您可以使用异步方法

let url = URL(string: "https://example.com/image.png")
imageView.kf.setImage(with: url)

您可以使用库

下载性能将无法区分

但是,您应该使用URLSession或类似于翠鸟的库,翠鸟也使用URLSession,因为它可以让您更好地控制连接;b如果失败,它会提供更多的诊断信息;它提供取消功能。我们经常谈论不同方法的“优点和缺点”,但对于DatacontentsOf:,这只是“缺点”

话虽如此,我们有五种提高绩效的关键方法:

贮藏

确保在应用程序下载图像后,如果该单元格从视图中滚出,然后又回到视图中,您不会启动新的网络请求。您刚刚下载了资产,因此应该使用它。有时候,URLSession免费提供这种缓存,尽管它有点取决于web服务器的配置方式。因此,我们通常自己进行缓存,既有RAM中的小型缓存(例如NSCache),也有持久性存储中的大型缓存(例如。像翠鸟这样的库为您提供所有这些缓存

这并没有改善初始获取,但它通过避免重新获取已下载的内容而显著提高了性能

预取

您可以启用预取,在预取中,当完成对可见单元格的数据请求后,它将为可能很快滚动到视图中的单元格请求数据。这意味着,假设它有机会赶上,当您滚动时,它将显示已预取数据的单元格,并且在进行此操作时,它将预取下一个可能出现的单元格的数据

因此,同样,这并没有改善初始获取。但如果它有机会赶上,当你以适度的速度浏览时,它会感觉快得多

请参阅和UICollectionView文档中的“预取集合视图单元格和数据”讨论

取消

在集合视图中快速滚动时,需要确保取消对不再可见的单元格的请求。例如,如果您快速滚动以查看单元格100-119,您真的不希望在等待单元格0-99的图像时出现积压,因为这些图像不再可见

这就是为什么您确实希望使用基于URLSession的方法,在这种方法中,您可以保存对正在运行的URLSessionTask的弱引用,并在重新使用单元格时取消它。或者,如果使用翠鸟,我们将取消UIImageView的下载任务

下载适当大小的资产

如果可能,下载适当大小的资产。例如,假设图像是2000×2000像素。但假设你在一个3×视网膜设备上,它的图像视图是100×100点。这意味着您应该下载一个300×300像素图像360kb的数据,可能压缩到50-100kb以下,而不是2000×2000资产16mb的数据,甚至压缩到1mb以上。显然,这意味着您也下载了经过合理压缩的资产

诚然,如果您还没有实现此功能,那么在服务器上准备不同大小的资产是一项非常重要的工作,但是对于设计良好的web服务来说,准备不同大小的资产是很常见的;b提供API下载客户端应用程序所需的任何大小

如果下载大型资产以显示在小集合视图单元格中,这可能会对实际性能产生巨大影响

压缩

可能不用说,因为这是很常见的,但请确保服务器传输的资产得到充分压缩。例如,压缩质量为70-80%的JPEG看起来不错,但比未压缩的资源小得多。PNG也提供压缩,但通常不提供与JPEG相当的大小,因为它是一种无损压缩

总之,确保服务器上的资产被合理压缩,在质量和规模之间取得一些平衡。我的意思是,有些服务在压缩资产方面做得太过分了,严重降低了图像质量。我正在和你说话,Facebook,但是请为你的应用程序选择一个合理的平衡点

所以,我支持你
对像翠鸟这样的图书馆的其他建议。它简化了客户机代码,并自动提供了问题1“缓存”。但是问题2和问题3,预取和取消,需要您做一些工作,但是非常简单。如果您尚未拥有适当规模的资产,则第4版和第5版可能会产生最显著的影响,但您将受制于您的web服务。

您可以使用翠鸟图书馆……它是用纯swift开发的,易于使用且被开发人员广泛使用。您对其进行了测量吗?测试结果如何?第二种方法是否以并发模式下载图像?两者都同时下载
import KingfisherSwiftUI

var body: some View {
    KFImage(URL(string: "https://example.com/image.png")!)
}