iPhone SDK background thread image loading problem

Posted by retailevolved on Stack Overflow See other posts from Stack Overflow or by retailevolved
Published on 2010-05-31T11:34:07Z Indexed on 2010/05/31 11:53 UTC
Read the original article Hit count: 432

Filed under:
|
|
|

I have created a grid view that displays six "cells" of content. In each cell, an image is loaded from the web. There are a multiple pages of this grid (the user moves through them by swiping up / down to see the next set of cells).

Each cell has its own view controller. When these view controllers load, they use an ImageLoader class that I made to load and display an image. These view controllers implement an ImageLoaderDelegate that has a single method that gets called when the image is finished loading.

ImageLoader does its work on a background thread and then simply notifies its delegate when it is done loading, passing the image to the delegate method.

Trouble is that if the user moves on to the next page of grid content before the image has finished loading (releasing the GridCellViewControllers that use the ImageLoaders), the app crashes. I suspect that this is because along the line, an asynchronous method finishes and attempts to notify its delegate but can't because it's been released.

Here's some code to give a better picture:

GridCellViewController.m:

- (void)viewDidLoad {
    [super viewDidLoad];

    // ImageLoader  
    _loader = [[ProductImageLoader alloc] init];
    _loader.delegate = self;

    if(_boundObject)
        [_loader loadImageForProduct:_boundObject]; 
}

//ImageLoaderDelegate method
- (void) imageDidFinishLoading: (UIImage *)image {
    [_imgController setImage:image];
}

ProductImageLoader.m

- (void) loadImageForProduct: (Product *) product {
    // Get image  on another thread
    [NSThread detachNewThreadSelector:@selector(getImageForProductInBackground:) toTarget:self withObject:product];
}

- (void) getImageForProductInBackground: (Product *) product {
    NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];

    HttpRequestLoader *tempLoader = [[HttpRequestLoader alloc] init];

    NSURL *tempUrl = [product getImageUrl];

    NSData *imageData = tempUrl ? [tempLoader loadSynchronousDataFromAddress:[tempUrl absoluteString]] : nil;

    UIImage *image = [[UIImage alloc] initWithData:imageData];

    [tempPool release];

    if(delegate)
        [delegate imageDidFinishLoading:image];
}

The app crashes with EXC_BAD_ACCESS.

Disclaimer: The code has been slightly modified to focus on the issue at hand.

© Stack Overflow or respective owner

Related posts about iphone

Related posts about objective-c