How to manage memory with images
Okay, so if I written quite a lot of code without ever allocating any objects, where is the memory going?
For example, rather than having
UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];
I had
imageView.image = [UIImage imageNamed:@"image.png"];
throughout all my code. I don't see what is happening with the memory in the second example. I'm still learning, and wrote a lot of code using the second example throughout the entire app, without ever allocating any objects. It always ran fine in the simulator, but the actual device can't handle the memory and crashes. All the tutorials on memory management talk about it in the sense of releasing objects that you creat开发者_如何学Goe, but since I never created any objects, I'm stuck.
UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];
You made a double release. [UIImage imageNamed] is autoreleased so you don't need to explicitly release the object. Your app probably crashed because of double releases and not because of unreleased objects.
Read the simple rule of thumb, release/autorelease confusion in cocoa for iphone :
The rule is simple: if you alloc, copy or retain, it's your responsibility to release. If you didn't, it's not. However, if you need to rely on an object staying around, you have to retain (and subsequently release).
More examples:
imageView.image = [UIImage imageNamed:@"image.png"];
Above code is valid, you don't have to release it. But if you use a lot direct assignments with unreleased objects such as this one:
foo.bar = [[SomeClass alloc] initWithSomething:@"Init"];
You can just easily fix them by adding autorelease:
foo.bar = [[SomeClass alloc] initWithSomething:@"Init"] autorelease];
Or if you want the long but arguably more appropriate way (since you controlled when the object is released):
SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"];
foo.bar = tempVar;
[tempVar release];
imageView.image = [UIImage imageNamed:@"image.png"];
This line is awesome and correct.
in the implementation of the imageNamed:
method, it may allocate memory for a new UIImage
, instantiate a new UIImage
into that memory, and then autorelease
it before returning it. The autorelease pool drains after your code runs, deallocating the image object if nothing retained it.
So "where is the memory going?". It's going to the autorelease pool. But really, unless you call alloc
or copy...
or retain
you dont have to care.
As Manny notes, your first snippet does over release and is incorrect.
You're confusing declaring variables with allocating memory/objects. The important part of your code in both cases above is actually this:
[UIImage imageNamed:@"image.png"];
This code happens to invoke a class method on the UIImage class that does a number of things. One of these things is an allocation and initialization of a UIImage object. In your first example you stored this allocated object into a variable called myImage
. You then moved your shiny new object into another (class) variable, `imageView.image'.
UIImage *myImage = ...
In the second example you gave you are still storing this allocated object in a variable, except that in this case you skipped the intermediary assignment and stored the object directly into the class variable imageView.image
.
imageView.image = [UIImage imageNamed:@"image.png"];
One way to think of variables vs objects is to compare them to houses. In this scenario a variable is your address, and the object is your house. Several people can have your address, but no matter how many they are, when they choose to visit, they are going to the same house. So in your examples myImage
and imageView.image
are addresses pointing to the same house, or object, an instance of UIImage. In your example you don't actually need to create the intermediary variable unless you are using it for some other purpose.
As far as the crashes, you should read up on Apple's memory management guide. It may take awhile but you will get used to the standards that Apple follows with respect to retaining and releasing objects. Note that the new Automatic Reference Counting in XCode 4.2
alleviates alot of these problems but it also has its own learning curve. But to summarize, you are getting crashes because you are releasing an object you do not own. The class method imageNamed
on UIImage returns an auto-released instance of that class. You do not need to send it another release in your code, and that is the likely source of your program crashes.
精彩评论