Yep, if you see your app bailing out with out of memory, you probably want to check how you load images into UIImage instances. Apparently that problem existed since iOS SDK was released and has never been fixed. At least I could reproduce it back in 7.0.1. It’s not exactly a memory leak, though you may see app memory usage going up in Allocations and Leaks tool after you load large images.
Technically it’s not a bug. More like an oversight on Apple’s side. UIImage does caching for images. Problem is that memory cache may take too much memory and make app eventually crash in OUM situation. It’s also a time waster for people who are trying to catch memory leaks issues that don’t exist and, believe me, tools won’t help you much finding the issue.
So, if you dynamically load images with [UIImage imageNamed], try to replace it with non-caching alternative:
- (UIImage *)imageNamed:(NSString *)filename
{
NSString *path = [AppUtils pathForResource:filename];
UIImage *img = [UIImage imageWithContentsOfFile:path];
return img;
}
Apple’s docs confirms that imageNamed method indeed uses an image caching:
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.
Unfortunately, Apple does not provide a mechanism to control how images cached, so you have no choice but use the code similar to the example I’ve written above. If you need a cache for your images, then… well, you need to implement your own cache. Image caching implementation is outside of the scope of this article I’ll probably get back to it later. 😉