- (void)viewDidLoad {
[super viewDidLoad];
landscape.image = [UIImage imageNamed:#"tenerife1.png"];
}
I assign a new UIImage to the image property of an UIImageView object. I am not sure if that would result in a memory leak?
No, it should not. The old image should be automatically released when you set the new one, and the "imageNamed" method uses autorelease, so you should be OK there.
hey take into account imageNamed has serious memory issues as you loose control over its cache - ie: once you are done with your image, you cannot reclaim that memory. a quick google search would let you know how many people have faced problems with imageNamed
i was at the apple iphone tech talks and the guy giving the presentation confirmed the same damn thing - he suggested using imageWithContentsOfFile instead of imageNamed
if you just have couple of small images, its fine otherwise use imageWithContentsOfFile even though its a bit slower - and implement your own caching logic - check this great link on how to do it here
It depends on how the image property is defined. If it's defined as retain or, I suppose, even copy, it should be fine. You'll end up trying to reference deallocated memory and crashing your program if it's defined as assign.
Not ordinarily, but it would depend on how you've defined landscape.image. See post above. Be careful with using a lot of these:
[UIImage imageNamed:#"tenerife1.png"];
Since there is a tendency for these images to fill up memory, without getting released.
Related
In my app, I've used the line
[UIImage imageNamed:imageName]
whenever loading an image. As I understand it, this function caches images for later use - this is great, because most of the images are used more than once.
BUT - when I simulate a memory warning, the memory used by these images doesn't seem to be freed according - and since most of the memory is in fact used by the cached images, it is pretty important that any currently unneeded images are released from memory!
-
Is this the expected behavior, or do the images remain in memory due to the fact that it's only a simulated memory warning? Or, if I want to release these images, will I have to write my own category for UIImage that caches images but releases uneeded ones when memory is in short supply (or even better, has anyone already done this/shared the code for it)??
What I have done is create my own caching mechanism utilizing -initWithConentsOfFile which doesnt cache, and an NSMutableDictionary for storing, every image allocated is stored in the dictionary with the image name as the key. If a memory warning is reached you can release and nil the dictionary thus releasing all the memory allocated from the images.
This gives you complete control over the image caching. -imageNamed: uses its own caching mechanism that you have no control over when and where the allocated memory is released.
You should try this method as well.
EDIT: Heres my UIImage class extension (https://gist.github.com/2880240), overriding -imageNamed: with custom cache, upon receiving a memory warning you can simply use [UIImage freeCache]. Also included, is the ability to set autorelease on all images upon storing them in the cache, i.e: [UIImage setShouldAutorelease:TRUE]. FALSE by default.
Give it a try, Hope it helps!
If there is no more reference to the image it should get cleaned, don't worry about the internal caching mechanism (since its behavior is undocumented anyway). Do you have any code in place to remove any references (nil or release) to the images?
Are you using it in a UIImageView?
A lot of framework data is automatically managed with the app goes into the background. Data for images loaded with imageNamed: are discarded automatically, but UIImageView does not discard its data, so perhaps its the same with the low memory warning.
P.S.
If your app is suspended it won't receive the memory warning. And if its using a lot of memory then it'll probably be terminated. To reduce the chances of this (if its important) then you could use an NSPurgeableData which you store in an NSCache in order to flag stuff as being purgeable in the event of a low memory situation, the OS will then purge it for you.
I'm trying to find ways to cut down memory usage for my app right now, and I have an idea regarding UIImages. I make pretty extensive usage of UIImages, some of them common to multiple views. Is it a lot more memory efficient to instantiate a single UIImage and then use a pointer to that same image throughout the app rather than allocating a new UIImage for the same image in each view? Or, is the OS smart enough to sort of automatically cache a UIImage so that it is only stored in memory once? (doubt that's the case but I have to ask)
Thanks.
Straight from UIImage apple reference docs for imageNamed:
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.
You use a lot of images, so remember that [UIImage imageNamed:#""]; caches the images, so if you are having low memory problem use instead [UIImage imageWithContentsOfFile:#""]; that doesn't cache it. Maybe that can help you cut down memory usage.
When a view unloads set the GUI properties to nil in the viewDidUnload method of UIViewController subclasses.
Yes, it is more efficient to store a single UIImage and use pointers to it.
It is unlikely that the OS caches images in this way, and even if it did, using pointers gives you more fine control of when the image is released / deallocated so that you don't have to hope the OS is going to take care of it.
I thought that I was really close to release this new App of mine when I ran into a dead end. My code works without memory leaks in the simulator (Xcode 4.0.2) but reports memory leaks on my devices.
I think my issue is related to that I copy an object, because in my troubleshooting attempts I tried without a copy, and then the memory leak goes away (but of course so do my functionality!).
What I do is that I add a number of instances of a subclass of UIView to an array . This subclass(Cities of which cityToAdd is an instance) has two UIViews and some variables that I need to access at a later stage.
If I do this I get memory leaks on my devices:
[arrayOfCities addObject:[[cityToAdd mutableCopy] autorelease]];
But if I do this I don't (but loose functionality)
[arrayOfCities addObject:cityToAdd];
In the subclass I have this to handle the copying:
- (id)mutableCopyWithZone:(NSZone *)zone{
Cities *newCity = [[Cities allocWithZone:zone] init];
[newCity initWithCityName:cityName
onRing:ring
withTimeZone:timeZone
withTimeZoneOffset:timeZoneOffset
withDSTAngle:DSTAngle
andDST:isDST];
return newCity;
}
From Instruments I get this when testing on a device:
and when I drill down on the second row it shows this:
Finally my initWithCityName method (sorry for such a long post!!) I put it as a picture to get the colors and messages from Instruments...
Finally the UIIMage imageNamedUniversal is an extension to give me #2x images on the iPad (but I have tried with the normal imageNamed and get the same memory leaks).
I dont know where to start!! Appreciate any ideas.
Thanks
Why are you calling two initialization methods? You are calling init and initWithCityName....
Two things to consider:
After you add cityView and DSTView as subviews, you can and should release them.
And you are initializing newCity twice in your copyWithZone.
Thanks for fast replies and suggestions. You got me on the right track. The cityToAdd that I added to my array was added several times in a loop, but I kept the alloc and init outside of the loop. Once I moved it inside the loop it works in both simulator and device.
Weird that the simulator don't report that memory leak though...
Again, thanks for your fast replies!
In my iOS OBJC app, i use a object, specifically a UIImage. I always need this UIImage, specially when the user decides to switch orientations. The problem is I only get this image once and will need it for as long as the app runs. As a result, I have allocted this object and sent it a retain. I never release it, because if I do and the user switches orientation, that object could be realsed and I won't be able to do what I need to do and as a result the app will crash.
My Point: What do I do? Is what I'm doing bad because it creates a leak? And if so, how can I fix this?
Thanks.
It sounds like you're loading a single image once and keeping it around to reuse forever. That is perfectly fine, although if it's a large image that might not be needed constantly you might want to listen for memory notifications and release it then.
Problems with never releasing come in when you allocate large objects or large numbers of objects that are never released. Particularly if you continually re-allocate new instances of the "same" thing because you lose track of the old ones.
John. I have a different approach, load and release everywhere. You see, when you use [UIImage imageNamed:] then iOS caches the image. Next time you call [UIImage imageNamed:], it uses the cached image, from memory, very quickly. That way you can still code for clean memory (release all over the place, no retain) and iOS has your back.
I have two queries
I was running a sample app which having single view controller in it implemented. When I check the memory using Instrument it was showing 3.66 MB
. Wondered why it is taking so much of RAM as there is nothing much heavy in app.
When I have added UIImageview with the Image having size of 25 KB,then Memory uses go to 4.24 MB
[ I come to know the reason behind is "image is unpacked 320*480*4 = 580 KB" but need to debug more on this & it remains in cache ]
Along this I have also observed two scenarios
When we uses api [UIImage imageNamed:aName] for loading image, then calling [UIImageview release] doesn't have any effect.
But When we use
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:aName ofType:nil]];
Some memory is cleaned up when I call [UIImageview release]
In my app , I am going to use lot of images and that will cause a low memory and will crash the app.
Please provide me some ref or path to analyse why this behavior.
Thanks,
Sagar
Trying to fit your app in memory is a losing game. It'll lead you down weird paths of trying to figure out which sort of device you're running on, swapping in and out resources based on that, etc, etc.
The better option is to design your memory structure for ditchability, and then support a fairly harsh ditching regimen when you're notified of low memory conditions. Go ahead and use memory--it's there for that--and let the low memory warning be your signal to prune out unused resources.
A lot of people seem to feel bad that their application generates memory warnings. That's silly. The design pattern here is, eat all you want, but respond appropriately when you're told you're overweight. Given you're running on a broad range of devices with a broad range of memory profiles (an iPhone 3G has 1/4 the RAM of an iPhone 4 for instance), the best way is just to be sensitive to when you've filled memory.
The main hurdle you'll encounter is recovering from having ditched data. I find what works best is to explicitly set UIImage objects to nil, and then test for nil before using them, reloading them from the bundle or the network or whatever if necessary.
All that said: [UIImage imageNamed:] supports ditchability, but you don't have control over it. When a UIViewController subclass gets a memory warning, it will ditch cached UIImages that you've created with that method, but nothing you can do will make them go away until then. Even assigning a tiny something to the UIImage in question won't help because it's cached associated with the "name" that it's "Named", not the object that it is assigned to. So that method is good for images you're going to reuse a lot, but even so, it will get pruned when the time comes, and you need to respond appropriately.
Images, loaded with imageNamed, are cached in memory by UIKit, and images, loaded with imageWithContentsOfFile are not.