I’m loading images onto a UITableView asynchronously (GCD), and am seeing a strange behavior where the cell will “shutter” through multiple images before settling on one. It’s hard to describe in words, so I made a screen recording, where you’ll see that for a given cell, multiple images will shift through before it settles on one.
http://www.youtube.com/watch?v=PKuqng81QX4
I’m using a queue to fetch the image (from a REST endpoint), and then the main queue to set the image in the cell. Here’s the code snippet:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// ..after getting the cell:
dispatch_queue_t imageQ = dispatch_queue_create("imageQ", NULL);
dispatch_async(imageQ, ^{
NSString *galleryTinyImageUrl = someFunctionToGetThumbnailUrl;
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:galleryTinyImageUrl]];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = [UIImage imageWithData:imageData];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
});
});
dispatch_release(imageQ);
The fact that this is getting called multiple times in short time (i.e. a user flicks up on the table, triggering 30 of these cell image loads to fire off) causes concern for me whether all of the async threads “land” safely where they’re supposed to. The behavior I’m seeing (in the video) seems to validate that I’m doing something wrong here. I’d appreciate any specifics or broad approach suggestions you might have.
Thanks for the help!
Sounds like you did not properly implement reusing of cells.
Make sure to, when reusing a cell via
[tableView dequeueReusableCellWithIdentifier:blah]you set the cells image toniluntil the new image has been fully downloaded and is ready to be displayed.Also, when reusing a cell, cancel a potentially running request for its image to prevent having a image of a previous cell load slower and therefore overwriting the real one.