Your cells are being reused.
When cell goes out of screen it gets to internal UITableView
s 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 UITableViewCell
s 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.
As simple as:
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
}
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…