Karuppu MGR Karuppu MGR - 6 months ago 73
iOS Question

Loading a image using dispatch_async within cellForRowAtIndexPath

Im trying to load an image from an url.

Following is my code..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

UITableViewCell *cell = nil;

cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@""];

if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}

dispatch_async (dispatch_get_main_queue(), ^{

NSData * storeImageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:productImageArray[indexPath.row]]];

self.productImage.image = [UIImage imageWithData:storeImageData];
});

[cell.contentView addSubview:self.productImage];

return cell;
}


The problem is that,


  1. UI freezes till the image is loaded.

  2. Only the last cell is loading the image but the remaining cells are not loading the image.



How can I sort this out?

Answer

Try this one:

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.imageView.image = image;  

Or sometimes what I do is to update the model and then reload the cell at the specific indexPath:

  myModel.image = downloadedThumbImage;
  [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                  withRowAnimation:UITableViewRowAnimationNone];  


  - (UITableViewCell *)tableView:(UITableView *)tableView    cellForRowAtIndexPath:(NSIndexPath *)indexPath
  {
    static NSString *CellIdentifier = @"top50places";
    UITableViewCell *cell = [tableView   dequeueReusableCellWithIdentifier:CellIdentifier];

   //getting the selected row image 
  NSDictionary* currentImageDictionary=[self.topfifty objectAtIndex:indexPath.row];//topFifty is an array of image dictionaries

   UIImage *currentImage = [currentImageDictionary objectForKey:@"image"];

  if (currentImage) { 
      // we already fetched the image, so we just set it to the cell's image view
     cell.imageView.image = currentImage;
  }
  else {
       // we don't have the image, so we need to fetch it from the server  

   // In the meantime, we can set some place holder image
   UIImage *palceholderImage = [UIImage imageNamed:@"placeholder.png"];
   cell.imageView.image = palceholderImage;

  // set the placeholder as the current image to your model, so you won't 
  // download the image multiple times (can happen if you reload this cell while 
  // download is in progress)
  [currentImageDictionary setObject:palceholderImage forKey:@"image"];

  // then download the image
  // creating the download queue 
  dispatch_queue_t downloadQueue=dispatch_queue_create("thumbnailImage", NULL);

  dispatch_async(downloadQueue, ^{
     UIImage *downloadedThumbImage=[self getImage:currentImageDictionary] ;

     //Need to go back to the main thread since this is UI related
     dispatch_async(dispatch_get_main_queue(), ^{
            // store the downloaded image in your model
            [currentImageDictionary setObject:image forKey:@"image"];

            // update UI
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.imageView.image = image;    
     });
  });
  dispatch_release(downloadQueue);

   }

 return cell;
 }
Comments