Search code examples
iosobjective-cuitableviewsetneedsdisplay

Refreshing UITableViewCell after fetching image data by dispatch_async


I'm writing app that shows TableView with entries that contains images. I'm trying to fetch image by executing this line of code inside cellForRowAtIndexPath method:

cell.detailTextLabel.text =  [artistData objectForKey:generesKey];
dispatch_async(backgroundQueue, ^{
         NSURL *url_img = [NSURL URLWithString:[artistData objectForKey:pictureKey]];
        NSData* data = [NSData dataWithContentsOfURL:
                         url_img];
        cell.imageView.image = [UIImage imageWithData:data];
        [self performSelectorOnMainThread:@selector(refreshCell:) withObject:cell waitUntilDone:YES];
    });

After setting image I perform selector that contains:

-(void)refreshCell:(UITableViewCell*)cell{
    [cell setNeedsDisplay];
    [self.view setNeedsDisplay];
    [self.tableViewOutlet setNeedsDisplay];
}

And image is not shown but when I click on cell or scroll entire list, images are shown. Why my View is not refreshing? Did I missed something?


Solution

  • You'll could always reload the cell by calling [self.tableView reloadRowsAtIndexPaths@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

    In order to prevent the infinite loop once you successfully download an image you'll want to cache the results. How long you cache is up to you.

     NSCache *imageCache = [[NSCache alloc] init];
     imageCache.name = @"My Image Cache";
     UIImage *image = [imageCache objectForKey:url_img];
     if (image) {
        cell.imageView.image = image;
     } else {
        // Do your dispatch async to fetch the image.
    
        // Once you get the image do
        [imageCache setObject:[UIImage imageWithData:data] forKey:url_img];
    }
    

    You'll want the imageCache to be a property at the ViewController level. Don't create one each time incellForRowAtIndexPath