Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone - Most memory effecient way to initialize an image?

I've read that imageNamed: is bad when trying to initialize images. But then what is the best way? I am using imageWithContentsOfFile: and passing the path of an image in my resources folder

[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"]

This call is made some 30 times in a for loop.

Now when I run my app with instruments, I see that a lot of memory is used up by NSString for operations like the above one where we use string literals (@"jpg") Instruments shows the responsible caller as [NSBundle mainBundle] and this in turn points to the line when I use the string literal for the type.

So what is the most effective way of initializing images without using too much of memory?

I changed the statement to

img = [UIImage imageWithContentsOfFile:[bndl pathForResource:fileName ofType:extn]]

where extn is static and initialized to @"jpg". fileName keeps changing for each iteration of the for loop. But even then the maximum use of NSString is because of [NSBundle mainBundle] and [NSBundle pathForResource:OfType:] according to Instruments.

like image 343
lostInTransit Avatar asked Feb 28 '23 19:02

lostInTransit


1 Answers

I'd avoid using autoreleased objects where you can within a loop. If Instruments is reporting a lot of hits on the NSBundle pathForResource:ofType: call, I'd pull some of that processing outside of the loop.

My suggested implementation would look something like this:

NSString *resourcePath = [[[NSBundle mainBundle] resourcePath] retain];

for (int i = 0; i < 1000; ++i) 
{   
    ...

    NSString *pathForImageFile = [resourcePath stringByAppendingPathComponent:fileName];
    NSData *imageData = [[NSData alloc] initWithContentsOfFile:pathForImageFile];

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

    ... 

    [image release];
}

[resourcePath release];

You will be accumulating one autoreleased string (pathForImageFile), but that shouldn't be so bad. You could create and release an autorelease pool within the loop, but I would suggest doing that at most once every 10 or 100 loop passes, not every pass. Also, the retain and release on resourcePath may be superfluous, but I put it there in case you want to use your own autorelease pool somewhere in here.

like image 155
Brad Larson Avatar answered Mar 16 '23 13:03

Brad Larson