[iOS] imageNamed vs imageWithContentsOfFile

Yesterday evening, I wrote a very simple prototype ipad app to try out some stuf. Basically I’m just displaying some images fullscreen and swiping left/right gives you the next or previous picture.┬áPlenty has been written about the memory/caching difference between using [UIImage imageNames] vs [UIImage imageWithContentsOfFile] (see this and this and many more), but I was flabbergasted with the amount of memory my very simple app would eat just for displaying four (yes, 4!) images I had (click to enlarge).

 

 

21 MB dirty and 69 MB resident. Just for displaying 4 images that are about 300K each consecutively full screen. You can clearly see with each new image the memory goes up. I did some googling around, and quickly learned that the following line caused the huge memory footprint:


UIImage *currentImage = [UIImage imageNamed:[self.photos objectAtIndex:self.currentIndex]];

Apparently imageNamed caches images to faster display the next times you need them. I also found older iOS versions (2 and 3) leaked memory when using this method, but I believe this should be fixed in current version. For small icons and layout images, I can completely understand why you want to cache the images so aggressively. However, in this use case my image gallery could have potentially hundreds of full-screen images. I haven’t found any way to configure the size of the image cache.

It just doesn’t feel right to use that much memory. So I switched to use following code:


NSString *file = [[NSBundle mainBundle] pathForResource:[self.photos objectAtIndex:self.currentIndex] ofType:nil];

UIImage *currentImage = [UIImage imageWithContentsOfFile:file];

Which gives following memory usage

 

Memory is now down to around 7MB dirty size, but more importantly it stays constant! Performance-wise, I cannot see any difference in loading speed between the two versions.

So for me that’s pretty clear which approach I should take for this app. Even if the image cache is automatically cleared by iOS on low memory warnings, having a more tighter control on memory gives me that warm fuzzy feeling we all like.

 

5 Comments

  1. Andrew November 13, 2012

    Very nicely put. I can’t believe this is still an issue with iOS! I had an app that was loading some very large images with imageNamed. The app would load the 6th image, then crash unceremoniously, checking the logs showed a memory warning. I’m surprised the API doesn’t flush the cache after receiving a memory warning!

  2. JScarry February 11, 2013

    I have an app that works fine on iPad but if you scroll through the images quickly on iPod Touch it crashes. Looking at the dirty memory in VM Tracker showed that images were piling up and then getting dumped. Switching to [UIImage imageWithContentsOfFile:file] fixed it for me too.

    By the way, your spam filter is a pain in the butt.

  3. Joram Barrez February 13, 2013

    @JScarry: Good to hear you managed to solve it!

    Sorry about the spam filter. How is it a pain? It’s a default wordpress plugin, didn’t give it much thought so far …

  4. Alex May 23, 2013

    Oh man. I wish I paid more attention to difference between imageNamed and imageWIthContentOfFile. I’ve wasted two weeks on chasing memory leaks (non-existent) and optimization (which was not a bad idea). App kept crashing after loading images dynamically at random places. Apple, please, fix the caching!

  5. Hamidreza Vakilian April 17, 2014

    UIImage renders images with high CPU Time and huge memory usage, whilst HyperImageView is a an alternative for UIImageView which renders images 30 times faster than UIImageView while uses 10 times less RAM. Also the rendering task is processed in background and it never blocks user interaction.

    http://hyperimageview.com

Leave a Reply

Your email address will not be published. Required fields are marked *