swift:在后台加载图像数据 [英] swift: load the image data in background

查看:29
本文介绍了swift:在后台加载图像数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to load 100 images in cells. If I use this method in tableView cellForRowAt:

cell.cardImageView.image = UIImage(named: "\(indexPath.row + 1).jpg")

并开始快速滚动我的 tableView 冻结.

and start scrolling fast my tableView freezes.

我使用此方法在修复冻结的后台加载图像数据:

I use this method to load the image data in background that fix freezes:

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
}

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

But I have one bug may arise in this approach, such that while scrolling fast I may see old images for a while. How to fix this bug?

推荐答案

您的单元格正在被重用.

Your cells are being reused.

当单元格离开屏幕时,它会进入内部 UITableView 的重用池,当你在 tableView(_:) 中 dequeueReusableCell(withIdentifier:for:) 时cellForRowAt:) 你再次得到这个单元格(参见名称中的可重用").理解UITableViewCell 的生命周期很重要.UITableView 不会保存 100 个活的 UITableViewCell 100 行,这会降低性能并使应用程序很快就没有内存.

When cell goes out of screen it gets to internal UITableViews reuse pool, and when you dequeueReusableCell(withIdentifier:for:) in tableView(_:cellForRowAt:) you get this cell again (see, "reusable" in name). It is important to understand UITableViewCell's life cycle. UITableView does not hold 100 living UITableViewCells for 100 rows, that would kill performance and leave apps without memory pretty soon.

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

Why do you see old images in your cells? Again, cells are being reused, they keep their old state after reuse, you'll need to reset the image, they won't reset it by themselves. You can do that when you configure a new cell or detect when the cell is about to be reused.

就这么简单:

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

另一种方法是检测重用和重置.在您的单元格子类中:

The other way is detecting reuse and resetting. In your cell subclass:

override func prepareForReuse() {
    super.prepareForReuse()
    self.cardImageView.image = nil // reset
}

为什么你在你的单元格中看到错误的图像?到时候 completion 闭包将图像设置为 cardImageViewUITableViewCell 已被重用(甚至可能不止一次).为防止出现这种情况,您可以测试是否在同一单元格中设置图像,例如,将图像名称与单元格一起存储,然后:

Why do you see wrong images in your cells? By the time completion closure sets image into cardImageView, UITableViewCell has been reused (maybe, even, more than once). To prevent this you could test if you're setting image in the same cell, for example, store image name with your cell, and then:

// 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
}

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

There is a lot of stuff to take care of when designing lists, I won't be going into much detail here. I'd suggest to try the above approach and investigate the web on how to handle performance issues with lists.

这篇关于swift:在后台加载图像数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆