在 UITableView 的单元格中下载图像的最佳实践? iOS/斯威夫特

Posted

技术标签:

【中文标题】在 UITableView 的单元格中下载图像的最佳实践? iOS/斯威夫特【英文标题】:Best practices for downloading images in a UITableView's cells? iOS/Swift 【发布时间】:2017-09-12 08:36:24 【问题描述】:

所以我在工作中讨论了在 UITableView 的单元格中下载图像更好的方法。

这两个选项是: 在 cellForRowAtIndex 中,我异步下载了图像,这导致使用多个线程和多个网络请求,我们怀疑这可能是电池消耗的问题。

另一种选择是使用一个线程和一个网络请求一次下载所有图像,方法是遍历一个包含所有图像 URL 的数组,该数组位于粗略的 cellForRowAtIndex 之外,然后调用表格视图重新加载函数。

对后一种方法也有一点修改,我们可以在每张图片下载后立即设置每张图片(可能通过调用 reload 函数)。

所以我很想知道,处理此问题的行业标准方法是什么?特别是在性能方面有什么优点和缺点?有没有更好的办法?

【问题讨论】:

只使用一个线程会导致下载过程缓慢,我建议您使用经过验证的第三方库之一,如SDWebImageKingFisherAlamofire 或任何其他您想要的 为什么异步下载图片比同步下载相同数量的图片更耗电? 有人告诉我,这一说法来自谷歌和业内其他领先公司所做的基准测试。我认为这与一遍又一遍地唤醒网络芯片有关? 多线程下载不应该使用额外的电池(至少不会显着更多);不缓存图像,以便您在 tableview 滚动时重复下载相同的图像。要么使用NSCache 实现缓存,要么使用建议的第 3 方库之一,看看是否有帮助。 正如@ReinierMelian 所说,使用SDWebImage 或Alamofire 下载tableviewcells 的图像。使用缓存来减少网络负载。还假设 tableviewcells 很小,请使用缩略图(较小)而不是全尺寸图像。 【参考方案1】:

我一般用SDWebImage,它会缓存图片,以后可以重复使用。它通过其扩展和各种方法提供了灵活性。

检查我实现的代码:

import UIKit
import SDWebImage

extension AcceptedWinksViewController: UITableViewDataSource 
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: Constants.CellIdentifier.WinkListTableViewCell) as! WinkListTableViewCell
        let profile = self.winkList[indexPath.row] //Model
        let placeHolderImage = UIImage(named:"placeHolder") //your placeholder image, can be class or global variable
        if let url = profile.imageURL 
            cell.userImageView.sd_setImage(with: url, placeholderImage: placeHolderImage, options: .refreshCached, completed: nil) //check its various options
        
        else 
            cell.userImageView.image = placeHolderImage
        
        return cell
    

【讨论】:

是的,这对缓存图像很有好处,但是如何处理第一次下载呢?它是否异步处理? 是的,它是异步处理的,根据图片url来做图片下载队列,请参考它的sdk代码以便更好地理解【参考方案2】:

以下是我的最佳实践;

如果您有很多图像/单元格,比如说 1000 个,请不要全部下载。用户不能滚动到底部。仅下载可见单元格。 图像下载后,检查单元格是否仍然可见。 Tableview 有一个 indexPathsForVisibleRows 属性,您可以获取所有可见的单元格 indexPaths。如果单元格不可见,则不应附加图像。 您显然应该在后台线程上异步下载它们。但是您应该限制最大并发操作数。您可以使用操作队列来执行此操作。否则,如果系统会创建很多线程(超过理想),性能会更差。我不确定理想的计数。只需尝试几个并比较结果。 您应该缓存下载的图像并且不应该一次又一次地下载。只下载一次。您可以使用字典将它们缓存在内存中。 下载图像后,将其附加到主线程上的单元格。否则,如果你附加在后台线程上,它会变慢。 您还可以实现取消机制。如果单元格变得不可见,最好取消下载。这可以通过操作和操作队列来完成。使用 GCD 更难做到这一点。 在下载图像之前使用占位符图像。

用于电池消耗;

根据 Apple 的能效指南,与逐个下载相比,批量下载项目更好。但是,这里有一个踩点。在我看来,与电池消耗相比,性能在这里具有最高优先级。

【讨论】:

以上是关于在 UITableView 的单元格中下载图像的最佳实践? iOS/斯威夫特的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UITableView 单元格中添加标签和图像视图的数量

UITableView 单元格中重叠图像的问题

在 UITableView 单元格中的图像上填充

UITableView 单元格中的图像不支持 tintColor

更新 UITableView 单元格中的特定按钮图像

UITableview 的每个单元格中的不同图像