IPhone - The most efficient memory method for initializing an image?

I read that imageNamed: is bad when trying to initialize images. But then the best way? I am using imageWithContentsOfFile: and passing the image path in the resource folder

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

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

Now, when I launch my application using tools, I see that most of the memory is used by NSString for operations similar to those described above, where we use string literals (@ "jpg") The tools show the responsible caller as [NSBundle mainBundle], and This in turn points to a string when I use a string literal for a type.

So what is the most efficient way to initialize images without using too much memory?

I changed the instruction to

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

where extn static and initialized to @"jpg" . fileName continues to change for each iteration of the for loop. But even then, the maximum use of NSString is due to [NSBundle mainBundle] and [NSBundle pathForResource:OfType:] according to the tools.

+4
source share
4 answers

I would not use auto-implemented objects where you can in a loop. If the tools report multiple hits to the NSBundle pathForResource: ofType: call, I would pull some of this processing out of the loop.

My proposed 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 accumulate one auto-implemented line (pathForImageFile), but it should not be so bad. You can create and free the autostart pool in a loop, but I would suggest doing this no more than once every 10 or 100 cycles, and not every pass. Also, saving and releasing on a Pat resource may be redundant, but I put it there if you want to use your own abstract pool somewhere around here.

+5
source

imageNamed: bad in some cases because it caches the image after loading it. Therefore, if you intend to reuse an image - a pretty likely case for something in your application bundle - using imageNamed: excellent. However, if you have many different images and you only upload once, you will want to avoid it.

If you do not want to use imageNamed: first part of the code will be fine. If you are worried about temporary lines created in your loop, put this before the loop:

 NSAutoreleasePool * pool = [NSAutoreleasePool new]; 

And this is after:

 [pool release]; 

This ensures that any temporary objects in the loop will be freed after the loop exits. However, make sure that all temporary objects that you want to save are saved. (For example, the images themselves must be added to a data structure that saves them, such as an array, dictionary, or set, or saves them manually.)

+2
source

What you can do is make sure you free auto-implemented objects in a loop

Before:

 for (int i = 0; i < 1000; ++i) { UImage* img = [UIImage imageWithContentsOfFile: [bndl pathForResource:fileName ofType:extn]]; ... } 

After:

 for (int i = 0; i < 1000; ++i) { NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init]; UImage* img = [UIImage imageWithContentsOfFile: [bndl pathForResource:fileName ofType:extn]]; ... [ap release]; } 

But I doubt that these NSString instances can cause too many problems:

  • UIImages should occupy much more memory than strings (> = 100x).
  • If your loop has only 30 iterations and you fall into the event loop, the auto-resource pool will be released, so you will not see more than 30 lines. (Event without an access point in a loop)

Are you sure you are interpreting the output of the tools correctly? Are you sure other parts of your code do not leak these lines? (The code shown in the question looks fine)

+1
source

I have not seen anyone mention this yet, but the reason you see multiple NSString instances created by this line is because pathForResource: ofType: you need to combine the lines together to create the full path from the various components ( directory name, file name, extension).

I am firmly in the camp "Don't worry about it." Compared to memory usage, even for a very small image, several dozen instances of NSString are just noise. If your loop goes from 30 images to several thousand or something else, then you might want to create an NSAutoreleasePool inside the loop.

0
source

All Articles