5

I have a UICollectionView with a custom UICollectionViewCell class which adds another UIView (thumbnailView) to its contentView. This other view has a UIImageView property (imageView) whose image gets loaded with SDWebImage asynchronously. This all works fine until the cell is reused while the image of the original cell is still being loaded. If you scroll fast enough through the CollectionView images start to pop up in cells where they are not supposed to be (probably because the cell got reused and the image download finishes afterwards), just to get replaced as soon as the correct image for the reused cell finishes loading.

To fix this, I added the following to my UICollectionViewCell subclass to stop the original cell's image download:

- (void)prepareForReuse
{
    [super prepareForReuse];
    [self.thumbnailView.imageView cancelCurrentImageLoad];
}

But to my surprise, this seems to change absolutely nothing. Am I doing something wrong or am I just looking in the wrong direction?

Tobi Kremer
  • 618
  • 6
  • 22

6 Answers6

4

Swift 4 - Add to your cell's class:

override func prepareForReuse() {
  super.prepareForReuse() 
  self.contentImageView.sd_cancelCurrentImageLoad()
  self.contentImageView.image = UIImage(named: "") // set to default/placeholder image
}
budiDino
  • 13,044
  • 8
  • 95
  • 91
3

If I understand your problem correctly, you are getting old images still appearing in reused cells so in addition to stopping the previous image load you probably want to remove the old image from the imageView. SDImageView might have a method to clear the image or else you could just manually replace it with a placeholder image.

- (void)prepareForReuse
{
    [super prepareForReuse];
    [self.thumbnailView.imageView cancelCurrentImageLoad];
    [self.thumbnailView.imageView setImage:<<LOCAL PLACEHOLDER IMAGE>> forState:UIControlStateNormal];
}
Stuart
  • 659
  • 6
  • 5
2

The UITableViewDelegate and UICollectionViewDelegate method -tableView:didEndDisplayingCell:forRowAtIndexPath: is the best place to update your UITableView | UICollectionView cells after it has disappeared. You can cancel the cell downloads there.

edsancha
  • 89
  • 9
2

SWIFT 4

Before setting new image to imageView add:

cell.imageView.sd_currentDownloadTask?.cancel()
Syscall
  • 19,327
  • 10
  • 37
  • 52
Ilya Biltuev
  • 166
  • 1
  • 7
0

I tried both didEndDisplayCell() and prepareForReuse(), neither of them work. A work round way is to set imageView.image as nil then assign to the specific image, then it will not blink the old image as background. (but it will be slower since it has to do the "clean" job first).

Yao Li
  • 2,071
  • 1
  • 25
  • 24
0

Eventually, I solve the problem by using static cells programmatically & download images by SDWebImage separately, try to handle the image from cache from another manager.

here's the SDWebImage code.

 [imageView sd_internalSetImageWithURL:url placeholderImage:nil options:SDWebImageRetryFailed context:nil setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
    
 } progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
    
 } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
    
    if (image) { imageView.image = image; }
    
 }];
Bomi Chen
  • 81
  • 4