views:

34

answers:

2

I am a little confused about releasing memory for array elements that are shared by multiple arrays. Here's the scenario:

Manager class has an instance variable NSMutableArray* mgrArray

Helper class has an instance variable NSMutableArray* helperArray.

Manager's init method:

NSMutableArray* mgrArray = [[[NSMutableArray alloc] init] autorelease];
    for (int i=0; i<10; i++) {
        Food *f = [[[Food alloc] initWithType:@"Fruit"] autorelease];
        [mgrArray addObject:f];
    }

Helper's init method:

NSMutableArray* helperArray = [[[NSMutableArray alloc] init] autorelease];

The manager object passes some of the mgrArray elements to Helper class to store for Helper's own access purposes (say for efficiency). Some Manager method that does this:

Food *e1 = [mgrArray objectAtIndex:3];
Food *e2 = [mgrArray objectAtIndex:5];
Food *e3 = [mgrArray objectAtIndex:7];

[helper. helperArray addObject:e1];
[helper. helperArray addObject:e2];
[helper. helperArray addObject:e3];

Question 1: when adding e1 to helperArray, should it be copied or retained or is it alright as written above?
Question 2: who should release the memory of the food objects and how?

+1  A: 

If you put an object in an array, it retains it. If you remove an object from an array, the array releases it.

It is that simple; ownership -- retains -- should always be bounded by lines of encapsulation.

If you need to ensure that an object remains alive when you are using it, retain it. The one edge case is if you do something like:

foo = [someArray objectAtIndex: 0];
[someArray removeObjectAtIndex: 0];

At that point, foo may have been released. To fix:

foo = [someArray objectAtIndex: 0];
[foo retain];
[someArray removeObjectAtIndex: 0];
.. do stuff ..
[foo release];

Question 1: when adding e1 to helperArray, should it be copied or retained or is it alright as written above?

Simply add e1 to the helperArray. Done.

Question 2: who should release the memory of the food objects and how?

When the array is released to the point of being dealloc'd, all objects contained within the array will be released (but not necessarily deallocated unless nothing else holds a retain).

bbum
Thanks for the response! "When the array is released to the point of being dealloc'd" -- are you referring to when the array retain count goes to zero, and it gets deallocated automatically?
twinkle
Yup. Exactly -- except that the retain count *might* not be zero at that point. The absolute retain count at any given time is an implementation detail of the whole system. Best not to think in terms of absolute retain counts.
bbum
+1  A: 

An object will be retained when added to an array and released when removed from an array.

If you are using an autoreleased object there is nothing else to do.

If you are using a regular object, you can release it after it is added to the first array.

jessecurry