Ios swift:在后台加载图像数据

Ios swift:在后台加载图像数据,ios,swift,uitableview,Ios,Swift,Uitableview,我需要在单元格中加载100个图像。如果我在tableView cellForRowAt中使用此方法: cell.cardImageView.image = UIImage(named: "\(indexPath.row + 1).jpg") 然后开始快速滚动mytableView冻结 我使用此方法在fix冻结的背景中加载图像数据: func loadImageAsync(imageName: String, completion: @escaping (UIImage) -> ()) {

我需要在单元格中加载100个图像。如果我在tableView cellForRowAt中使用此方法:

cell.cardImageView.image = UIImage(named: "\(indexPath.row + 1).jpg")
然后开始快速滚动my
tableView
冻结

我使用此方法在fix冻结的背景中加载图像数据:

func loadImageAsync(imageName: String, completion: @escaping (UIImage) -> ()) {
    DispatchQueue.global(qos: .userInteractive).async {
        guard let image = UIImage(named: imageName) else {return}
        DispatchQueue.main.async {
            completion(image)
        }
    }
}
tableView cellForRowAt
中,调用以下命令:

loadImageAsync(imageName: "\(indexPath.row + 1).jpg") { (image) in
        cell.cardImageView.image = image
}

但我有一个错误可能会出现在这种方法中,这样在快速滚动时,我可能会看到旧图像一段时间。如何修复此错误?

在单元格类中,您需要声明

override func prepareForReuse() {
    super.prepareForReuse()
}

要准备单元以供重用

您的单元正在被重用

当单元格离开屏幕时,它进入内部
UITableView
s重用池,当您
tableView(uu:cellForRowAt:)
中退出可重用单元格(标识符为:)
时,您将再次获得此单元格(请参阅名称中的“可重用”)。了解
UITableViewCell
的生命周期非常重要
UITableView
无法容纳100行的Live
UITableViewCell
s,这将降低性能,并使应用程序很快失去内存

为什么在单元格中看到旧图像? 同样,单元格被重复使用,重复使用后它们保持原来的状态,你需要重置图像,它们不会自己重置图像。您可以在配置新单元或检测单元何时将被重用时执行此操作

简单到:

cell.cardImageView.image = nil // reset image
loadImageAsync(imageName: "\(indexPath.row + 1).jpg") { (image) in
        cell.cardImageView.image = image
}
另一种方法是检测重用和重置。在单元格子类中:

override func prepareForReuse() {
    super.prepareForReuse()
    self.cardImageView.image = nil // reset
}
为什么在单元格中看到错误的图像?
完成时
关闭将图像设置为
cardImageView
UITableViewCell
已被重用(甚至可能不止一次)。为了防止出现这种情况,您可以测试是否在同一单元格中设置图像,例如,将图像名称存储在单元格中,然后:

// naive approach

let imageName = "\(indexPath.row + 1).jpg"
cell.imageName = imageName
loadImageAsync(imageName: imageName) { (image) in
    guard cell.imageName == imageName else { return } 
    cell.cardImageView.image = image
}

在设计列表时,有很多东西需要注意,我在这里不会详细介绍。我建议尝试上述方法,并在网上调查如何处理列表的性能问题。

@matt为什么我的问题没有说明?也许我应该添加更多的信息?这是合理的显示旧图像一段时间,除非新图像加载,旧图像显示。在我看来,如果还没有加载新图像,您可以使用占位符来显示。@matt您能举个例子吗?因为我在网上搜索这个,但没有任何帮助。我需要声明
prepareforeuse
?并使用cell.cardImageView.image=UIImage(名为:“\(indexPath.row+1.jpg”)?没有其他内容?如果我添加prepareforuse(),则不会有任何更改