views:

42

answers:

3

Let's say I have an object that has other objects in it. For example an NSMutableArray object "list" that has a few other objects.

If I no longer use any of them, can I just type [list release]?

Or do I have to release the objects in the list 1 by 1? ie.

for (int i=0; i < [list count]; i++)
    [[list objectAtIndex(i)] release];

If I have to do it one by one, wouldn't it be kinda troublesome if I have an object that has many other objects in it? Let's say a Picture object that has all kinds of Shape objects in it. Is there a better way?

+3  A: 

As long as you have no other references to the objects in the list, then releasing the NSMutableArray alone should be sufficient.

Stephen Darlington
+1. The array handles the retain/releasing on the items it contains.
Joe
+3  A: 

Let's check out that snippet of code keeping the Cocoa Memory Management rules in mind. I'm going to modify it slightly:

for (int i=0; i < [list count]; i++)
{
    id anObject = [list objectAtIndex(i)] ;
    [anObject release];
}

This is just so I can talk about anObject, otherwise it is identical to your code.

Now, you obtained anObject by sending objectAtIndex: to an array. Here is the relevant quote from the rules:

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.

  • Does objectAtIndex: start with alloc? No.
  • Does objectAtIndex: start with new? No.
  • Does objectAtIndex: contain copy? No.
  • Did you retain anObject? No.

Therefore, the last bolded sentence applies.

You must not release anObject. The release in the code is incorrect.

I've written the above out at some length not to try to slap you down and make you look stupid, but because I used to find this stuff just as confusing as you do and the only way I could stop my code from leaking or crashing was by mentally ticking off the answers to those four questions pretty much for every object I used. It doesn't take long for it to become second nature such that you can glance at a piece of code and instantaneously figure out what needs releasing.

JeremyP
A: 

If you do something like the following, you do not have to release each object, because you do not use alloc, copy, new, or retain on the added object.

NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithInt:15]];

If, however, you alloc your object before adding it to the array, you will want to release it.

NSMutableArray *array = [[NSMutableArray alloc] init];
id anObject = [[MyObject alloc] init]
[array addObject:anObject];
[anObject release];
Josh