Episode #90

Table View Images in iOS 7

10 minutes
Published on October 10, 2013

This video is only available to subscribers. Get access to this video and 572 others.

In this episode we continue our example from Episode 89, using NSURLSessionDataTask to download images for our rows. We also see how we can benefit from the built-in cache settings of NSURLSessionConfiguration and how to efficiently request images while scrolling.

Episode Links

Creating a download task on the cell

By tracking the download task as a property on our cell, we can easily cancel the request when it is reused for another row.

@interface MediaCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
@property (weak, nonatomic) IBOutlet UIImageView *artworkImageView;
@property (weak, nonatomic) IBOutlet UILabel *collectionNameLabel;

@property (nonatomic, strong) NSURLSessionDataTask *imageDownloadTask;

@end

In our view controller's cellForRowAtIndexPath: method we can kick off the download:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   // other cell setup code

    if (cell.imageDownloadTask) {
        [cell.imageDownloadTask cancel];
    }

     cell.artworkImageView.image = nil;
    NSURL *imageURL = [NSURL URLWithString:record[@"artworkUrl100"]];
    if (imageURL) {
        cell.imageDownloadTask = [self.session dataTaskWithURL:imageURL
                                             completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                 if (error) {
                                                     NSLog(@"ERROR: %@", error);
                                                 } else {

                                                     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                                                     if (httpResponse.statusCode == 200) {
                                                         UIImage *image = [UIImage imageWithData:data];
                                                         dispatch_async(dispatch_get_main_queue(), ^{
                                                             cell.artworkImageView.image = image;
                                                         });
                                                     } else {
                                                         NSLog(@"Couldn't load image at URL: %@", imageURL);
                                                         NSLog(@"HTTP %d", httpResponse.statusCode);
                                                     }
                                                 }
                                             }];
        [cell.imageDownloadTask resume];
    }
}

There are a few nice things about this. First, the images are cached automatically, taking advantage of our session configuration's caching settings. The defaults work fine for our example. Second, requests are cancelled if the rows scroll off screen, so if you scroll fast we don't waste time loading images you won't see.