views:

35

answers:

1

I have a method that asynchronously downloads images. If the images are related to an array of objects (a common use-case in the app I'm building), I want to cache them. The idea is, I pass in an index number (based on the indexPath.row of the table I'm making by way through), and I stash the image in a static NSMutableArray, keyed on the row of the table I'm dealing with.

Thusly:

@implementation ImageDownloader

...
@synthesize cacheIndex;

static NSMutableArray *imageCache;

-(void)startDownloadWithImageView:(UIImageView *)imageView andImageURL:(NSURL *)url withCacheIndex:(NSInteger)index
{
    self.theImageView = imageView;
    self.cacheIndex = index;
    NSLog(@"Called to download %@ for imageview %@", url, self.theImageView);


    if ([imageCache objectAtIndex:index]) {
        NSLog(@"We have this image cached--using that instead");
        self.theImageView.image = [imageCache objectAtIndex:index];
        return;
    }

    self.activeDownload = [NSMutableData data];

    NSURLConnection *conn = [[NSURLConnection alloc]
            initWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
    self.imageConnection = conn;
    [conn release];
}

//build up the incoming data in self.activeDownload with calls to didReceiveData...

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Finished downloading.");

    UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
    self.theImageView.image = image;

    NSLog(@"Caching %@ for %d", self.theImageView.image, self.cacheIndex);
    [imageCache insertObject:image atIndex:self.cacheIndex];
    NSLog(@"Cache now has %d items", [imageCache count]);

    [image release];

}

My index is getting through okay, I can see that by my NSLog output. But even after my insertObject: atIndex: call, [imageCache count] never leaves zero.

This is my first foray into static variables, so I presume I'm doing something wrong.

(The above code is heavily pruned to show only the main thing of what's going on, so bear that in mind as you look at it.)

+1  A: 

You seem to never initialize the imageCache and probably got lucky with it having the value 0. The initialization would best be done in the class' initialization, e.g.:

@implementation ImageDownloader
// ...
+(void)initialize {
    imageCache = [[NSMutableArray alloc] init];
}
// ...
Georg Fritzsche
Huh. I kind of wondered about initializing it. Doing it in `-(ImageDownloader *) init` was obviously wrong. Didn't cross my mind there's a CLASS initializer. This MIGHT now be working, except that I now (correctly, I suppose) get an out-of-range error the first time I go `if ([imageCache objectAtIndex:index]) {`. While we're here, how DO you conditionally test an array index in Obj-C?
Dan Ray
`if (index < [imageCache count])`
Alex Reynolds