UIImage implementation / paging? - ios

From the UIImage documentation:
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.
What about UIImages that were not loaded from a file, but instead drawn, say, with UIGraphicsGetImageFromCurrentContext()?
I'm trying to come up with ways to optimize the memory usage of UITableViewCells with UIImageViews containing UIImages as the cells enter and are pulled from the reuse queue.
Thoughts?

Mike,
My understanding is that CGImage data is gone, so I think (this for your custom drawn image point) you are out of luck?
I actually just dealt with a similar issue with UITableViews. One thing that I did for performance was to create cells with a Nib; this was the single largest boost in performance of all the things I did, so if you are not using a Nib consider it.
You might also consider some form of preloading if you have that much data. I don't know what you are trying to implement, so this may or may be applicable.
One other note, after purging UIImage's reloading them from their files is a significant memory hit, so if you are at that point you really need to just look at memory usage overall.

Related

iOS - Optimizing. Cache images

I'm trying to optimize an iOS application which contains a lot of images and code. I have reduced the size of images with some programs but using instruments reveals that the application is still taking among 70-90mb of cache memory.
I have read that loading the resources(images) by demand and discard them when are not longer needed would be a good solution. How can i do it?
I have also a question:
When we use:
UIImage *aux = [UIImage imagenamed:#"image.png"];
and after we write aux=nil;
the image is discarded from cache?
Are only some of those images visible at a time? Write a system that loads only those images currently visible (and perhaps some that you application thinks might become visible soon). When you get a memory warning from the system, look for some images you've loaded in the past that haven't been visible for a while and release them.
To answer your second question, yes, setting a reference to nil will release it IF you are using ARC (Automatic Reference Counting), and if the reference you set to nil is the only reference to that object. All references to an object must go away before it will be released.
I would look at some of the solutions available, such as Path's FastImageCache, and see if they meet your needs. FastImageCache stores uncompressed images on disk in a format similar to Sprite Sheets (used by 2D games) so they can be loaded quickly when needed. The emphasis here is on improving scrolling performance, so if that's not an issue for you, this might not be the right tool for the job.
You might also look at this thread, although this is aimed at caching web images.
You might also take a look at The Tumblr Image Cache

save many UIImage to NSMutableArray without memory leak or similar method

I am trying to do screen capturing and saving many images into NSMutableArray. Then, I will call those images and make video. I can successfully make video. However, the problem is that I can't save many images into NSMutableArray. The application crash. I would like to know how to save those images temporarily. (not in document directory).
You will quickly run out of memory if you try to store all of those images in an array. You have two options:
Even though you say you don't want to save all of those images to the Documents folder, that might be your best approach. Save them to Documents, and then have your video creation process load the images one at a time and add them to the video.
Alternatively, you can do the renderInContext of your view that you want to capture directly to the CGContextRef that you've set up for your CVPixelBufferRef, do the appendPixelBuffer, and but then CVPixelBufferRelease immediately.
Either of these approaches will avoid holding all of the images in memory at any given time, mitigating the out of memory situation. I profiled both approaches, and each avoids the constantly growing consumption of memory that the loading of images to an array suffers.

How to improve performance of UITableView loading hundreds of Images from Documents Directory?

I'm loading a list of image files from the Documents Directory and setting them inside a Custom UITableViewCell, however, my previous efforts have either been too memory heavy, or resulting in bad UITableView scrolling performance.
In each of these methods, I load the image into container class, and then an array.
What I have tried:
UIImage+ImmediateLoad (A Custom UIImage category that loads an image from a file path and loads it straight into the memory. This results in 60FPS scrolling, but crashing of the application if the user has over 100+ Albums.)
The MPMediaItem valueForProperty:MPMediaItemPropertyArtwork method. (This however, causes the scrolling frame rate to drop dramatically. I don't think this directly loads the images into memory (correct me if I'm wrong).)
Passing the file path to the UITableViewCell itself, and having it load the image. This results in slow scrolling too, but also does not throttle memory.
These images can be up to 1MB each.
In short (and I know I'm asking for a lot), I'm asking for a way to load images for the Documents directory that isn't too hard on memory, and scrolls smoothly.
Another strategy is to have an ordered list of image paths and a matching mutable array. Say the user is at location 0. Load images say 0-10 in the array. As the user scrolls always keep the last n images, free older ones (put NSNull in the mutable array), and prefetch the next n. Where this struggles is during active scrolling, sinc too much background work can cause scroll stutter. However it reduces memory pressure by only keeping a relatively small set of data in memory at any given time.
Other thoughts. You can save UIImageViews instead of just the images. Instead of tossing out of range images, throw them in a NSCache.
If all else fails you can do what PhotoScrollerNetwork does, and prerender the images in one massive file, then use mmap to grab the pixels for any given image and quickly create a a CGImage. Here you trade off the file system space for speed.

Is there any performance or memory overhead using UIImage or UILabel or NSString in Quartz2D

Is there any performance or memory overhead using UIImage or UILabel or NSString in Quartz2D.
If there is no difference then why not use UIImage, UILabel etc.
Can any one send me the snippet how to draw image without using UIImage.
Thanks in advance,
Regards.
please correct me if you see any stupid mistake I am new to this, trying to learn it.
A label draws a string. You can't have a label without a string; if you did, what would it draw?
Last I checked, UILabel uses UIWebView internally, so you could indeed make a more efficient version. One way would be to use Core Text; the other would be to use a CATextLayer.
As for UIImage, technically yes; a UIImage wraps a CGImage, so cutting out the UIImage would save some memory. However, 99% of the memory used by an image is for the image itself, its pixels; those are contained within the CGImage, and the UIImage is tiny compared to it. You have better things to spend your time cutting.
Rather than guessing and/or relying on generalities for your optimizations, use Instruments to find out exactly what your application is spending its memory on. Once you know with hard evidence where all your memory is going, you'll know where you can look for savings.
Wrappers generally won't increase memory usage much; objects are small, so you'll only pay a lot for them if you create a lot of them. Look instead to shortening their lifetimes; don't hold onto objects (in caches, collection objects, or directly in instance variables/properties) any longer than you need to.

UIImageView not releasing image data properly?

In its simplest form, my app displays 10 UIImageViews, each containing an image. Even with all UIImageViews containing images, my app uses a small enough memory footprint. However, there is a button to clear all the UIImageViews by setting all their images to nil. The problem is, when checking Memory Monitor in Instruments, the memory held by the UIImageViews is NOT going away. This doesn't appear in the Allocations instrument, confirming the remaining memory footprint is not an object, but instead graphics-based memory. If I resize the images to something smaller or larger, the memory remaining is also smaller or larger, respectively.
Why is the image data sticking around after the UIImageView's image has been set to nil?
I believe UIKit keeps a cache of images for reuse. UIImageView might be releasing the object, but a copy is kept around for performance reasons.
These images, though, should be released on receiving a memory warning. If they're not, there's two places I'd check:
Make sure the UIImageView is being dealloc'd. Use Allocations Instrument to profile your app and do whatever you need to do in the program to load those images. Then unload the images and do a search for UIImageView. As long as you're sure your program should have released all of them, if you find any in the search you know something is wrong.
I'd also check any places the image was created, for example: UIImage = [UIImage imageName:#"Foo.jpg"]; Make sure these are also being released. You can use allocations to find UIImage classes, but it'll be harder to weed out the ones that should/should not be there.
Run the static analyzer: In Xcode 4 it's under Products -> Analyze. This is a great tool for finding logic errors, over/under release (if you not using ARC) etc.
Until actual UIImageViews are themselves released, their memory will remain allocated. Additionally, if you're using convenience methods on UIImage to obtain your images, eg:
UIImage *myImage = [UIImage imageNamed:#"myImage"];
Note that your image may cached behind-the-scenes by iOS, and so even if the image is being released by you, the memory footprint may still reflect the presence of the image in memory (eventually iOS will release it, so this shouldn't adversely impact your resource consumption).

Resources