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;
}
}
}];
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];