person
person

Reputation: 123

SDWebImage repeating images in cell instead of waiting to load.

I am using SDWebImage for fetching images from server to my table view app in IOS. But the problem is that when I scroll down in table view instead of waiting for the images to load it put the images downloaded in the first few rows of table view and repeat those images till the end row and when it downloads the images it changes those repeated images to the actual image for that row.

      NSURL * url = [NSURL URLWithString:string];

    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    [manager downloadImageWithURL:url
                     options:0
                    progress:^(NSInteger receivedSize, NSInteger expectedSize)
     {
         // progression tracking code
     }
                   completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished,NSURL * url)
     {
         if (finished && image  )
         {

             NSArray *visibleIndexPaths = [tableView indexPathsForVisibleRows];
                 if ([visibleIndexPaths containsObject:indexPath]) {

                         cell.myImage.image = image;

                 }

         }

     }];

Upvotes: 1

Views: 1208

Answers (1)

Giru Bhai
Giru Bhai

Reputation: 14398

Actually, it is not a bug with SDWebImage, but rather it's the nature of how UITableView works. downloadImageWithURL, is an async process,so when your tableView delegate/datasource methods are called, the image isn't downloaded yet, therefore cellForRow doesn't have an image to display. To overcome this issue you should first check image from cache as

[[SDWebImageManager sharedManager] diskImageExistsForURL:[NSURL URLWithString:ImageUrl]]

if yes then set image to UIImageView otherwise use downloadImageWithURL to download image and add cell tag(To display image to correct row) as

cell.tag = indexPath.row;

on successfull download first check correct row as

if(cell.tag == indexPath.row){

and set image to UIImageView.Here is setImage method.

-(void)setImage:(SLFirstTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{
    SLFirstTableViewCellItem * slFirstTableViewCellItem = [self.categories objectAtIndex:indexPath.row]; // categories is array of items,replace with yours.

    NSString *ImageUrl = slFirstTableViewCellItem.imageUrl; //assume image url is in slFirstTableViewCellItem object.

    cell.tag = indexPath.row;

    if([[SDWebImageManager sharedManager] diskImageExistsForURL:[NSURL URLWithString:ImageUrl]]){
        [cell.imgItem setImage: [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:ImageUrl]];
        [self hideProgressView:cell];
    }else{
        [self showProgressView:cell];

        [SDWebImageDownloader.sharedDownloader downloadImageWithURL:[NSURL URLWithString:ImageUrl]
                                                            options:0
                                                           progress:^(NSInteger receivedSize, NSInteger expectedSize)
         {
             // progression tracking code
         }
                                                          completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
         {

             if (image && finished)
             {
                 [[SDImageCache sharedImageCache] storeImage:image forKey:ImageUrl]; // cache image

                 if(cell.tag == indexPath.row){ // check if correct row
                     [cell.imgItem setImage:image];
                     [self hideProgressView:cell];
                 }
             }else{
                 cell.imgItem.hidden = YES;
                 cell.progressBar.hidden = YES;
             }
         }];
    }
}

And define showProgressView and hideProgressView methods as

-(void)showProgressView:(SLFirstTableViewCell *)cell {
    cell.progressText.hidden = NO;
    cell.progressBar.hidden = NO;
    cell.imgItem.hidden = YES;
    [cell.progressBar startAnimating];
    [cell.progressText setText:@"Loading Image..."];
}

-(void)hideProgressView:(SLFirstTableViewCell *)cell{
    cell.progressBar.hidden = YES;
    cell.progressText.hidden = YES;
    cell.imgItem.hidden = NO;
    [cell.progressBar stopAnimating];
}

finally call setImage from cellForRowAtIndexPath method(before returning cell) as

[self setImage:cell atIndexPath:indexPath];

Upvotes: 4

Related Questions