TheM00s3
TheM00s3

Reputation: 3711

reloading UItableViewCell after thumbnail image downloads

I have an app in which within the tableViewCell an image is downloaded and than set as a thumbnail. My problem is that the only way I can see the thumbnail image refresh is if I click on another tab, and than come back to the tab that the tableViewCell is being held. Below is the code for setting the thumbnail.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    PFObject *message = [self.messages objectAtIndex:indexPath.row];
    cell.textLabel.text = [message objectForKey:@"username"];
    cell.imageView.image = [UIImage imageNamed:@"Treehouse.png"];
    PFFile *thumbnail = nil;

   if (thumbnailArray.count > 0){
    thumbnail = [[thumbnailArray objectAtIndex:indexPath.row] objectForKey:@"imageFile"];
   dispatch_async(backgroundQueue, ^{

           NSURL *thumbnailURL = [[NSURL alloc]initWithString:thumbnail.url];
           NSData *thumbnailData = [NSData dataWithContentsOfURL:thumbnailURL];

          [[cell imageView]setImage:[UIImage imageWithData:thumbnailData]];
       [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];


   });
   }


    return cell;
}

Upvotes: 3

Views: 3064

Answers (3)

TheM00s3
TheM00s3

Reputation: 3711

The following code helped solve my problem

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    PFObject *message = [self.messages objectAtIndex:indexPath.row];
    cell.textLabel.text = [message objectForKey:@"username"];
    cell.imageView.image = [UIImage imageNamed:@"Treehouse.png"];
    PFFile *thumbnail = nil;

   if (thumbnailArray.count > 0){
    thumbnail = [[thumbnailArray objectAtIndex:indexPath.row] objectForKey:@"imageFile"];
   dispatch_async(backgroundQueue, ^{

           NSURL *thumbnailURL = [[NSURL alloc]initWithString:thumbnail.url];
           NSData *thumbnailData = [NSData dataWithContentsOfURL:thumbnailURL];
           dispatch_sync(dispatch_get_main_queue(), ^{
               [[cell imageView]setImage:[UIImage imageWithData:thumbnailData]];
               [tableView reloadInputViews];
           });
   });
   }


    return cell;
}

The problem was that reloading the TableView was being called on a separate thread. Once I moved the setting of the image onto the main thread and calling reloadInputViews from there, my problem was fixed.

Upvotes: 1

nprd
nprd

Reputation: 1942

The problem is.,

  1. The cell is loaded.
  2. The image download is fired.
  3. Once image is downloaded, the cell is reloaded.
  4. The image is downloaded again.
  5. There is no caching of the image or logic to load the image

Declare a NSMutableDictionary @property (strong) NSMutableDictionary *imagesDictionary; and instantiate it self.imagesDictionary = [NSMutableDictionary dictionary];

In cell for Row at index path, check for the presence of cache before downloading it.

PFFile *thumbnail = nil;

if (thumbnailArray.count > 0)
{
 //If image is present in cache load from cache
UIImage *image = [self.imagesDictionary objectForKey:indexPath];
if (image)
{
    [cell.imageView setImage:image];
}
else
{
    //If Image is not present fire a download
     thumbnail = [[thumbnailArray objectAtIndex:indexPath.row] objectForKey:@"imageFile"];
     dispatch_async(backgroundQueue, ^{

        NSURL *thumbnailURL = [[NSURL alloc]initWithString:thumbnail.url];
        NSData *thumbnailData = [NSData dataWithContentsOfURL:thumbnailURL];

         //Cahce it to your image dictionary
        [self.imagesDictionary setObject:[UIImage imageWithData:thumbnailData] forKey:indexPath];
         //Reload the dictionary
        [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];


    });


}

Upvotes: 2

adrian
adrian

Reputation: 582

I recommend you use AFNetworkings category UIImage+AFNetworking which allows you to just do [imageView setImageWithURL:(NSURL)] which manages everything in the background. You don't have to worry about loading the image, caching the image or anything like that. It will cache it for you.

https://github.com/AFNetworking/AFNetworking

Upvotes: 1

Related Questions