具有图像视图并通过网络模型的单元格:重用时会发生啥?
Posted
技术标签:
【中文标题】具有图像视图并通过网络模型的单元格:重用时会发生啥?【英文标题】:Cells with image view and passed a model for networking: what happens when reused?具有图像视图并通过网络模型的单元格:重用时会发生什么? 【发布时间】:2017-09-09 20:37:41 【问题描述】:我有一个表格视图,其单元格显示使用URLSessionDownloadTask
下载的图像。我已经看过几个教程/帖子处理必须检查调用以下载某个图像的单元格是否没有被重用并且仍然必须显示这样的图像的常见场景,或者通过设置和稍后检查单元格的标签,或者持有并稍后检查调用/接收的图像的 URL。
但是在那些教程/帖子中,网络任务是从 tableView(_:cellForRowAt:)
方法中的视图控制器调用(然后我看到单元格的标签被选中),或者从 UITableViewCell
子类调用(然后看起来通常检查图像的 URL)。在这些情况下,我知道在调用完成下载任务时可能已经重用了一个单元格。但我的情况有点不同,我不太清楚这是否也会发生:
在我的tableView(_:cellForRowAt:)
中,我将模型对象传递给单元格。然后,调用下载任务的是模型,而不是单元格本身。这是我从tableView(_:cellForRowAt:)
调用的UITableViewCell
中的方法,用于为每个单元格配置适当的模型:
func configureCell(_ model: MyCellModel)
// Some label's texts are set here
model.getPicture (picture) in
imageView.image = picture
而getPicture
是这样的:
func getPicture(completion: @escaping (UIImage?) -> Void)
let request = URLRequest(url: url!)
let task = session.downloadTask(with: request, completionHandler: (fileUrl, response, error) in
if let data = try? Data(contentsOf: fileUrl), let image = UIImage(data: data)
DispatchQueue.main.async
completion(image)
else
DispatchQueue.main.async
completion(nil)
)
task.resume()
因此,当调用tableView(_:cellForRowAt:)
并重用一个单元格时,它会“注入”一个新模型。然后该模型执行调用以下载该单元当时需要的图片。
单元格不包含对其模型的引用。
那么单元格是否有可能在重新使用之前获得所需的图像并要求新的图像?
编辑:也许我应该更好地解释一下我关心的问题:对于我的场景,如果我开始下载图像,然后重新使用单元格,然后再使用它的模型,这不是问题“死”并且下载没有完成和/或我没有在单元格中得到这样的图像,因为我不再需要那个图像了。
我的担心是相反的:如果一个单元开始下载一个图像,并且在它得到这样的图像之前,这个单元被重用并注入一个新模型,我知道它以前的模型应该被杀死。但是,是否仍然可以调用它的完成闭包,然后在单元格中获取我不再需要的以前的图像?也许是因为它的@escaping
?然后我是否应该注意检查在这种情况下我在单元格中获得的图像?
【问题讨论】:
【参考方案1】:此时单元格无法处理数据。您有一个模型正在检索单元格的数据,并且在检索后,模型死亡(没有引用被保留)..
在这种情况下,模型必须进行某种缓存。或者网络层必须进行缓存。
AFNetworking 的实现方式(伪代码):
class model
func download(url: URL, completion:(img: UIImage?, error: Error?) -> Void)
if let img = cache.find(url)
completion(img, nil);
else
taskManager.downloadImage(url, (img, err) in
cache.put(url, img)
completion(img, err)
);
【讨论】:
谢谢。如果我开始下载图像,然后重新使用单元格,然后其模型“死亡”并且下载没有完成/图像不会发送回单元格,这不是问题,因为我不再需要这样的图像了。所以我也不需要缓存它。我的担心实际上是相反的:如果一个单元开始下载图像,并且在它获得这样的图像之前,单元被重用并注入新模型,则应该杀死以前的模型。但是,是否仍然可以调用它的完成关闭,然后将我不再需要的以前的图像放入单元格中?也许是因为它的@escaping
?
@AppsDev 在模型的 deinit 中,取消请求即可。它永远不会实现,一切都会好起来的。至于缓存,每次单元格滚动进出视图可见区域时,一遍又一遍地下载相同的图像并不是一个好主意。以上是关于具有图像视图并通过网络模型的单元格:重用时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
UITableViewCell中的UIButton标题在重用时会发生变化
uicollectionview 可重用单元格图像在滚动时加载
UITableViewCell 中的 UIButton 标题在重用时发生变化