title: Asynchronous UITableViewCell Image Loading Using GCD
body: <p>I'm currently trying to load a UITableView list of Flickr Photo (cs193p iOS Stanford, assignment 5). To avoid UI blocking event, I've deferred the thumbnail download of each cell into a different queue (but do update the UI back in the main queue). This code doesn't asynchronously load the images, though does add a thumbnail once I click on of the UITableViewCell row. (see screenshots below). Any idea what i'm doing wrong? </p>
  
  <p>PS: I've looked already in a few other stackoverflow questions &amp; Apple's LazyTableImages example, but I remain convinced this is the cleanest way to achieve the desired result. </p>
  
  <p>Thanks!</p>
  
  <pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  {
      static NSString *CellIdentifier = @"Photo List Cell";
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  
      // Configure the cell
      NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row];
  
  
      if (photo != nil) {
          if ([[photo objectForKey:@"title"] length] &gt; 0) {
              cell.textLabel.text = [photo objectForKey:@"title"];
          } else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] &gt; 0) {
              cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"];
          } else {
              cell.textLabel.text = @"Unknown";
          }
      }
      cell.imageView.image = [[UIImage alloc] initWithCIImage:nil];
  
      // Fetch using GCD
      dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL);
      dispatch_async(downloadThumbnailQueue, ^{
          UIImage *image = [self getTopPlacePhotoThumbnail:photo];
          dispatch_async(dispatch_get_main_queue(), ^{
              if ([self.tableView.visibleCells containsObject:cell]) {
                  [cell.imageView setImage:image];
              }
          });
      });
      dispatch_release(downloadThumbnailQueue);
  
      return cell;
  }
  </code></pre>
  
  <p>Before clicking a row
  <img src="https://i.stack.imgur.com/s2U2Y.png" alt="Before clicking a row"></p>
  
  <p>After selecting the row
  <img src="https://i.stack.imgur.com/Kmtkq.png" alt="After selecting the row"></p>
  
  <p><strong>UPDATE: For those interested, this is the final code I used:</strong></p>
  
  <pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  {
    static NSString *CellIdentifier = @"Photo List Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  
    // Configure the cell
    NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row];
  
    if (photo != nil) {
      if ([[photo objectForKey:@"title"] length] &gt; 0) {
          cell.textLabel.text = [photo objectForKey:@"title"];
      } else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] &gt; 0) {
          cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"];
      } else {
          cell.textLabel.text = @"Unknown";
      }
    }
    cell.imageView.image = [[UIImage alloc] initWithCIImage:nil];
  
    // Fetch using GCD
    dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL);
    dispatch_async(downloadThumbnailQueue, ^{
      UIImage *image = [self getTopPlacePhotoThumbnail:photo];
      dispatch_async(dispatch_get_main_queue(), ^{
          UITableViewCell *cellToUpdate = [self.tableView cellForRowAtIndexPath:indexPath]; // create a copy of the cell to avoid keeping a strong pointer to "cell" since that one may have been reused by the time the block is ready to update it. 
          if (cellToUpdate != nil) {
              [cellToUpdate.imageView setImage:image];
              [cellToUpdate setNeedsLayout];
          }
      });
    });
    dispatch_release(downloadThumbnailQueue);
  
    return cell;
  }
  </code></pre>