Loading images into NSArray using initWithObjects crashes but not with an NSMutableArray?
-
22-09-2019 - |
Question
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?
Solution
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]
OTHER TIPS
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.