views:

65

answers:

4

I have been very confused on how to handle the releasing of an NSMutableArray when I need to return it from a method. I am not even sure if I am suppose to release it or not.

I have the code:

-(NSArray *)methodToCall {

        NSMutableArray *mutArray = [[NSMutableArray alloc] initWithCapacity:10];

        //Fill the array with stuff here

        [mutArray release];  //Am I suppose to have this to keep the memory down?
        return mutArray;
}

My question is whether or not I am suppose to have the [mutArray release]; in the code or not. Could someone explain this? I am at a loss and I want to keep my code as clean and leak free as possible.

+6  A: 

The caller of your method is going to expect a valid NSArray, but which it doesn't own.

If you release it the way you're doing in your question, you're returning an invalid object (because you've both allocated and released it.) So that's not what you want.

You should "autorelease" the array before returning it. Then you'll be allocating it, but relinquishing ownership (without forcibly releasing it) before returning it. It will be valid until the end of the current event loop when the autorelease pool gets cleaned up, and your caller can retain it or let it go as appropriate:

-(NSArray *)methodToCall {

    NSMutableArray *mutArray = [[NSMutableArray alloc] initWithCapacity:10];

    //Fill the array with stuff here

    return [mutArray autorelease];
}

Your other alternative, since you don't need to keep the reference around either, is to use one of the "autoreleasing" convenience methods to create it in the first place:

-(NSArray *)methodToCall {

    // We're not doing an explicit alloc/init here, so...
    NSMutableArray *mutArray = [NSMutableArray arrayWithCapacity:10];

    // ...no autorelease necessary.
    return mutArray;
}
quixoto
+4  A: 

Short answer - No.

As it is now, you are allocating an array and then releasing (freeing) it before the return. So the when you try accessing the return object from your calling method you're going to get a crash.

My suggestion would be to use autorelease or to have the calling method or class ivar be responsible for this array object if it is used often.

An example of the autorelease:

NSMutableArray *mutArray = [[[NSMutableArray alloc] initWithCapacity:10] autorelease];

I also suggest reading the Memory Management from the Developer Documents.

Jason McCreary
+1  A: 

In general, instead of using alloc/init to create a temporary array, consider using a convenience creation method (-arrayWithCapacity: in this case):

- (NSArray *)methodToCall
{
    NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:10];

    // Fill the array with stuff here

    return mutableArray;
}

Convenience creation methods such as -arrayWithCapacity: return an object that the caller is not responsible for, relieving the calling code of the burden of managing memory. Since the calling code is simply returning the reference rather than storing it, that'll simplify things.

jlehr
A: 

if you go for explicit object allocation by calling alloc and init you are owner of your object, so you are responsible for its object retain value else you do it by implicit you don't need to care about it. it will take care of itself.

-(NSMutableArray *)getArray
{
     NSMutableArray *array=[[NSMutableArray alloc] initWithCapacity:10];

     //your code

    return [array autorelease];
}

in the above code we are the owner of the object so we need to handle its retain count by passing autorelease the autoreleasepool will take care of it.

-(NSMutableArray *)getArray
{
     NSMutableArray *array=[NSMutableArray allocWithCapacity:10];

     //your code

    return array;
}

in the above code we didn't alloc any object we just call class method to define the size of the array.

if you want more details go for the object ownership in Memory management guide from apple library

KingofHeaven