Question

I have a Table View with a load of cells with a UIImageView in each of them.

The images are loaded asynchronously from the internet and appear in the relevant cell once each image been downloaded.

The issue I'm facing is that until every image has loaded, I can't tap on a cell to segue it to another view that's linked to it.

I'm using dispatch_async(dispatch_get_global_queue(0, 0), ^{[self getItemImagesAsync:urlArray];}); to start the async process that loads the images.

the getItemImagesAsync method is here:

- (void) getItemImagesAsync:(NSArray *)urlArray{

NSMutableArray *imageArray = [[NSMutableArray alloc] init];

ResizedImageData = imageArray;

for (NSString *searchString in urlArray) {

    if (!shouldContinueLoadingImages) {
        return;
    }

    [imageArray addObject:[self getImageFromURL:searchString]];
    ResizedImageData = imageArray;

    [self.tableView reloadData];
}

}

The shouldContinueLoadingImages variable is set to false when the view changes (due to a search function) to stop unnecessary loading of images.

All of the image data is held in the NSArray ResizedImageData

So that the entire table doesn't have to wait for the images to download before rendering, the code uses a try statement in the cellForRowAtIndexPath method to see if an image exists in the image data array:

@try {
        cell.imageView.image = [ResizedImageData objectAtIndex:indexPath.row];
    }
    @catch (NSException *exception) {}

Is there some basic concept that I'm missing here, or is it something different?

Was it helpful?

Solution

This code has a few issues. You are reloading the data in a background thread. You are reloading the table view a lot. Each time you reload the data you throw multiple exceptions.

There is a simpler approach:

NSAssert([urlArray count] > indexPath.row, @"There are more rows than image URLs");
NSInteger index = indexPath.row;
NSString *URLString = [urlArray objectAtIndex:index];

// Prep the cell to download the image
cell.imageView.tag = index; // cell needs to remember which image it's downloading.
cell.imageView.image = nil; // Remove the image from the previous use of cell.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    // Download the image in the background
    UIImage *image = [self getImageFromURL:URLString];

    dispatch_async(dispatch_get_main_queue(), 0), ^{
        // Back on the main thread, set the image in the cell.
        if (cell.imageView.tag == index) { // only if the cell is on the same index.
            cell.imageView.image = image;
        }
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top