views:

1003

answers:

2

I'm doing some lazy loading of images into an array when the app has loaded. I have tried using an NSMutableArray and an NSArray (I don't need to alter the array once it's been created) but the latter crashes on me.

...
[self performSelectorInBackground:@selector(loadImageArrays) withObject:nil];
...

- (void)loadImageArrays {

    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *fileName; 

    imageArray = [[NSMutableArray alloc] init];
    for(int i = 0; i <= x; i++) {
        fileName = [NSString stringWithFormat:@"image_0000%d.png", i];
        [imageArray addObject:[UIImage imageNamed:fileName]];
    }
    [pool drain];
}

vs

NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
imageArray = [[NSArray alloc] initWithObjects:
            [UIImage imageNamed:@"image_00000.png"],
            [UIImage imageNamed:@"image_00001.png"],
            [UIImage imageNamed:@"image_0000X.png"],
                    nil];
[pool drain];

NSZombieEnabled = YES tells me that [UIImage retain] was sent to deallocated instance when using the latter code-snippet. Both arrays have (nonatomic, retain) property in my h-file. Why are the images not being retained by the NSArray?

A: 

Although I know there is a big difference in mutable and immutable arrays, I'm in doubt myself. Something tells me this isn't purely a mutable vs immutable issue. Looks like your pool is drained prematurely (sounds nasty). Not that it should make a difference, but could you try to spawn a new thread by doing;

[NSThread detachNewThreadSelector:@selector(loadImageArrays) toTarget:self withObject:nil];

I'm simply curious of the result.. Also try both snippets in a clean environment (i.e: with no other code around). If your second code snippet works there, you should be looking elsewhere for the solution.

MiRAGe
+3  A: 

UIImage is part of UIKit, which is not thread safe. For example, the method imageNamed: could corrupt the global name-image dictionary that the UIImage class uses for caching.

You have to use Core Graphics if you want to load images on a background thread.

Edit to answer your comment:

You can load PNG files with:

CGDataProviderRef source = CGDataProviderCreateWithURL((CFURLRef)url);
CGImageRef image = CGImageCreateWithPNGDataProvider(source, NULL, NO, kCGRenderingIntentDefault);
CFRelease(source);

A CGImage is a core foundation object and can be stored in an NSArray. You can then make a UIImage from it (on the main thread, of course):

[[UIImage alloc] initWithCGImage:image]
Nikolai Ruhe
While I appreciate the answer, how would I go about if I wanted to use Core Graphics to load the images in a background thread?
ressaw
On SO, if an answer leads you to more questions, you should make a new post.
Nikolai Ruhe
I'm sorry. Excellent answer, however. Thank you so much!
ressaw
Great, I didn't know that.. Well, at least I was partially right :-)
MiRAGe
Still, how is immutable and mutable related to this issue? Or was that just random behavior?
MiRAGe
@MiRAGe: exactly.
Nikolai Ruhe