cellForRowAtIndexPath: setNeedsDisplay not working for images downloaded in the background, even when calling it on the main thread

StackOverflow https://stackoverflow.com/questions/9335624

Question

I have seen a few posts which suggest using something like the following inside the block which downloads the images asynchronously in order to invoke setNeedsDisplayon the main thread and get it to display quicker.

dispatch_async(main_queue, ^{
                [view setNeedsDisplay];
            });

I'm trying this as can be seen below but the images are not being displayed as soon as they are downloaded. Generally there is about a 4 - 5 second delay. I know this because if I select any particular row, the image appears while the others are still not displayed.

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

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    UIImageView *iv = (UIImageView*)[cell viewWithTag:kCellSubViewWavImageView];;

        //async for scroll performance
        dispatch_queue_t queue = 
        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{

            NSURL *url = [[NSURL alloc] initWithString:[self.user.favWavformURLAr objectAtIndex:indexPath.row]];
            NSLog(@"background");
            NSData *imageData = [[NSData alloc] initWithContentsOfURL:url];
            UIImage *image = [[UIImage alloc] initWithData:imageData];

            iv.image = image;

            dispatch_queue_t main_queue = dispatch_get_main_queue();
            dispatch_async(main_queue, ^{
                NSLog(@"main thread");
                [iv setNeedsDisplay];
            });

        });

    }

    return cell;
}

Incidentally, the NSLog(@"background"); and NSLog(@"main thread"); calls below are printed in the following order for the call for the initial 6 cells, which is what I would expect, I think. But still doesn't work:

2012-02-17 20:46:27.120 SoundcloudFavs[8836:1c03] background
2012-02-17 20:46:27.169 SoundcloudFavs[8836:1b03] background
2012-02-17 20:46:27.170 SoundcloudFavs[8836:6b07] background
2012-02-17 20:46:27.173 SoundcloudFavs[8836:7503] background
2012-02-17 20:46:27.174 SoundcloudFavs[8836:7103] background
2012-02-17 20:46:27.177 SoundcloudFavs[8836:8003] background
2012-02-17 20:46:27.219 SoundcloudFavs[8836:207] main thread
2012-02-17 20:46:27.270 SoundcloudFavs[8836:207] main thread
2012-02-17 20:46:27.282 SoundcloudFavs[8836:207] main thread
2012-02-17 20:46:27.285 SoundcloudFavs[8836:207] main thread
2012-02-17 20:46:27.296 SoundcloudFavs[8836:207] main thread
2012-02-17 20:46:27.300 SoundcloudFavs[8836:207] main thread

Any ideas?

Was it helpful?

Solution

Try to set downloaded image in main thread.

dispatch_async(main_queue, ^{
            NSLog(@"main thread");
            iv.image = image;
        });

Also it is better to add images as subviews not for cell but cell.contentView.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top