views:

68

answers:

4

If I create a view, and add it as a subview and also add it to an array, do I have to release it twice?

    UIView* cat = [[UIView alloc] initWithFrame:someFrame];
    [self.view addSubview:cat];
    [self.animals addObject:cat];
    [cat release];
    [cat release];

It just seems weird to me to have 2 release statements, and I haven't seen people doing that. But doesn't the retain count increase by 2 in this case?

+8  A: 

You should only have one release — to balance the alloc. Neither addSubView: nor addObject: give the caller ownership over the object, so the caller does not need to balance them with a release. Reading the memory management guide should clear all this up for you.

It might help to remember "NARC" — if you call a method on an object that includes the word "*n*ew", "*a*lloc", "*r*etain" or "*c*opy", you need to release it. As you can see in your code above, only alloc fits the bill. Since you only NARCed it once, you only need to release it once.

Chuck
Thanks, I'll remember that.
sol
+2  A: 

When the cat is added to self.view, then self.view owns the cat, and it is responsible to release the cat. It is the same as for self.animals. The self.animals owns the cat. When self.animals is released, it will release all objects it owned.

So, you should release cat only one. Because in your code block, you own only one cat, not two.

Toro
ok one follow up question then - does self.animals = nil release the cat?
sol
I assume your animals is a structure of NSArray. When animals array is released, all objects inside array will receive a release message. So, the cat in the animals will be released.
Toro
+3  A: 

In addition to what Chuck wrote:

It's not that you release because addSubview: or addObject: might/might not increase the retain count.

That's completely wrong way to look at it. If self.view retains your object, it's self.view's responsibility to release it correctly, and that's nothing you should care about.

It's because you created the object by alloc you need to release it.

Yuji
A: 

As has been mentioned you do not have to release it twice; once is all that is required. However you do not have to release it at all if you use autorelease:

UIView* cat = [[[UIView alloc] initWithFrame:someFrame] autorelease];
[self.view addSubview:cat];
[self.animals addObject:cat];

The cat object will be released toward the end of the RunLoop cycle. Using autorelease will make your code cleaner and more able to cope with change.

Also you do not need the self qualifiers on view and animals unless you want to distinguish them from locally scoped objects (it'd also be poor practice to have locally scoped variables named the same as your classes' members).

Christopher Hunt