Reputation: 2153
What might be an acceptable solution for handling large amounts of images in memory?
Currently I'm building a photo-sharing application (in some sense similar to Instagram). I've been able to mimic their fast loading of many images in the feed (combining pre-loading and lazy-loading of images), but I'm a little stuck on what to do to handle the potential large memory footprint these images will have.
Is CoreData an option for temporary image storage? Is writing the objects to the temporary directory using NSCoder another option? I'm trying to proactively avoid memory crashes, and I'm unsure whether CoreData, a temporary folder, or some other means would be decent enough to reduce the memory footprint of (potentially) hundreds of images if the user scrolls in their feed pretty far. These also will not be permanent.
(For what it's worth, right now I have an object representation for each image that holds metadata and the image, and they are stored in a basic array structure. It works well for now, but I want to make sure if I'm loading hundreds of images I can reduce the memory footprint but still be able to quickly access these objects)
Upvotes: 0
Views: 1380
Reputation: 2018
CoreData is overkill if you're very simply storing a bunch of images. For efficiency you'd have to set it up to store the images outside the database anyway, so it'd probably end up being more work.
The obvious approach - of just saving all the images to files in a cache folder somewhere - is reasonable (though, as I'll explain shortly, possibly unnecessary). You can then recreate them as needed. By keeping your images in an NSCache where their 'cost' is their file size and you impose some a total cost limit you can keep a lid on the total memory consumption.
But ideally you could find a way to store the images on disk such that they can be mmapped in directly. This would let you just map them all in simultaneously and the VM system will essentially provide you an efficient LRU cache over them all. It's less contained, though - they'll also potentially steal memory from other parts of your app. It may also be tricky to find a way to do this using the high-level image classes (e.g. UIImage). But you can get close pretty easily - the UIImage documentation says:
In low-memory situations, image data may be purged from a UIImage object to free up memory on the system. This purging behavior affects only the image data stored internally by the UIImage object and not the object itself. When you attempt to draw an image whose data has been purged, the image object automatically reloads the data from its original file. This extra load step, however, may incur a small performance penalty.
So you could create UIImages using imageWithContentsOfFile:
, and they'll purge their in-memory copy of the image as necessary, and reload it if and when necessary (i.e. when draw again). They may not actually map the file, though - -[NSData initWithContentsOfMappedFile:]
is unfortunately deprecated from iOS 5 onwards.
Which approach makes sense depends on your usage requirements - if you're able to reliably predict which images you'll need, manually managing them may give you a better user experience since you'll be loading them ahead of time and avoiding delays during actual drawing.
Upvotes: 0
Reputation: 89559
I've run into this exact dilemma as you in a couple of my own apps, where I had to potentially display hundreds of UIImage objects in table views.
One of the solutions I did for my app was to not store the full resolution image in memory but instead a thumbnail (which I shrunk down using the UIImage+Resize.h category extension available and described here). And once the user decided to edit or make use of the photo, I then loaded the entire full resolution image.
You can also save these thumbnails (or at least their image data) to small files in the "~/Library/Caches/
" folders.
Upvotes: 2
Reputation: 46563
If performance is the concern then Core data gives you more granularity. Here you can save it by parts and lazy loading is also available for you.
Upvotes: 0