Loading GCD UITableView asynchronous loading images, invalid cells load before loading a new image

I have a UITableView with custom cells. I upload images asynchronously using Grand Central Dispatch. Everything works fine, but when I scroll down, previously uploaded images are loaded before the new image is uploaded. Here is my code:

if (![[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingPathComponent:@"image.png"]]) { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^{ NSString *url=[pat stringByAppendingPathComponent:@"comments.txt"]; NSString *u=[NSString stringWithContentsOfFile:url encoding:NSUTF8StringEncoding error:nil]; NSURL *imageURL=[NSURL URLWithString:u]; NSData *image=[NSData dataWithContentsOfURL:imageURL]; [image writeToFile:[pat stringByAppendingPathComponent:@"image.png"] atomically:YES]; dispatch_sync(dispatch_get_main_queue(), ^{ cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; [cell setNeedsLayout]; NSLog(@"Download"); }); }); } else { NSLog(@"cache"); cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; } 

Any suggestions appreciated. Postscript i reuse cells

+8
ios objective-c cocoa-touch uitableview
source share
3 answers

Instead of grabbing the cell, you need to grab the index path and then return the cell using:

 UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

Thus, if the cell is now turned off, you will get zero back, and the image will not be set to the wrong cell.

Another thing you need to add after dispatch_async() is cell.imageView.image=somePlaceholderImage .

eg:.

 if (![[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingPathComponent:@"image.png"]]) { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^{ NSString *url=[pat stringByAppendingPathComponent:@"comments.txt"]; NSString *u=[NSString stringWithContentsOfFile:url encoding:NSUTF8StringEncoding error:nil]; NSURL *imageURL=[NSURL URLWithString:u]; NSData *image=[NSData dataWithContentsOfURL:imageURL]; [image writeToFile:[pat stringByAppendingPathComponent:@"image.png"] atomically:YES]; dispatch_sync(dispatch_get_main_queue(), ^{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; [cell setNeedsLayout]; NSLog(@"Download"); }); }); cell.imageView.image=[UIImage imageNamed:@"placeholder"]; } else { NSLog(@"cache"); cell.imageView.image=[UIImage imageWithContentsOfFile:[pat stringByAppendingPathComponent:@"image.png"]]; } 
+18
source share

In your - (void)tableView:(UITableView *)aTableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { You need to clear the image or reset it from your counter. Since table view rows are reused, you will see this behavior.

+2
source share

Does UITableViewCell - (void) prepareForReuse define for this purpose? Override it and clear the image in it.

+2
source share

All Articles