9

i'm having an issue using SDWebImage to load images to a UIImageView inside a custom UITableViewCell. This is my code at the UITableView delegate:

    static NSString *userTableId = @"userTableId";
    UserDetailsTableViewCell *cell = (UserDetailsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:userTableId];
    NSDictionary *user = [userList objectAtIndex:indexPath.row];
    NSInteger position = indexPath.row + 1;
    [cell.userDetailsView loadFromDictionary:user WithIndex:position ForCharitie:false];
        cell.userDetailsView.delegate = self;

    cell.userDetailsView.delegate = self;
    return cell;

And here is my code for loadFromDictionary:

-(void) loadFromDictionary: (NSDictionary *) dic  WithIndex: (NSInteger) index ForCharitie: (BOOL) isCharitie{
    NSDictionary *userImageDic = [dic objectForKey:@"image"];
    NSString *url =[userImageDic objectForKey:@"url"];

    [userImage setImage:[UIImage imageNamed:@"defaultAvatar"]];
    if ([url class] != [NSNull class]){
        [userImage setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"defaultAvatar"]];
    }
}

Now, the problem is if i scroll down before some images finish loading. For example, let's say I see the first 8 rows, and rows 1, 2 and 3 still loading their images, now i scroll to 9-16, i see the defaultAvatar for all of them, and after a few seconds (i guess when images of rows 1,2 and 3 finish downloading), the images on cells 9, 10 and 11 change to the ones that belong to 1,2 and 3. I don't know if there is a way to stop the images from downloading when i reuse the cell, or something like that. Thank you and sorry for my English!

DemianArdus
  • 827
  • 8
  • 20

5 Answers5

16

If you have your UITableViewDelegate set on your table, you could use the delegate method:

- tableView:didEndDisplayingCell:forRowAtIndexPath:

to set the image to NULL (or the default) when your cell scrolls off screen.

And since you're using SDWebImage, canceling it could be as easy as "cancelCurrentImageLoad" on the cell's image view.

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • Thank you, i added `cancelCurrentImageLoad` before calling `loadFromDictionary` every time the cell will be reused. – DemianArdus May 19 '14 at 15:22
  • I am also using that library but I had no problems so far. This kind of problem happened with me when I was using dispatch and setting images inside threads, but thank you so much for your advice, it's really a nice hint. I really recommend this answer to anyone, who is having the same problem! – E-Riddie May 19 '14 at 15:27
  • but there a case if cell did display and still didn't finish load image itself! why cancel load image it? how you can handle this case? Thanks! – Marwan Alqadi Nov 05 '18 at 10:35
4

Override prepareForReuse method in your cell class and cancel all loadings there. Do not forget to call super

1

Example of answer above. Swift 3

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    (cell as! UITableViewCell).imageView.image = nil
    (cell as! UITableViewCell).imageView.sd_cancelCurrentImageLoad()
}
Andrii Solokh
  • 54
  • 1
  • 11
0

I was getting blank images with the accepted answer and given the images I'm loading are small, I wanted to let the images cache in the background and not cancel the load.

  1. Push a unique id on the stack before your closure and check it when your closure completes
  2. prepareForReuse

Like this:

func updateArtistImage(url: URL) {
        let _eventId = self.event?.id
        SDWebImageManager.shared().loadImage(with: url, options: [], progress: nil) { (image, data, error, cacheType, finished, url) in
            if self.event!.id == _eventId {
                if error == nil {
                    self.artistImageView.image = image
                } else {
                    self.artistImageView.image = UIImage(named: "error_image")
                }
            }
        }
    }

and this:

override func prepareForReuse() {
    super.prepareForReuse()
    self.artistImageView.image = nil
}
Tony
  • 18,776
  • 31
  • 129
  • 193
0

Just call sd_cancelCurrentImageLoad and set [imageView setImage:nil] before call sd_setImageWithURL.

[imageView sd_cancelCurrentImageLoad]; 
Bhavesh Patel
  • 596
  • 4
  • 17