views:

184

answers:

4

With an instance variable myArray:

@interface AppController : NSObject
{
    NSArray *myArray;
}

Sometimes I see myArray initialized like this:

- (void)init
{
    [super init];
    self.myArray = [[NSArray alloc] init];
    return self;
}

and sometimes I see it with a more complicated method:

- (void)init
{
    [super init];
    NSArray *myTempArray = [[NSArray alloc] init];
    self.myArray = myTempArray
    [myTempArray release];
    return self;
}

I know that there's no difference in the end result, but why do people bother to do the longer version?

My feeling is that the longer version is better if the instance variable is set up with a @property and @synthesize (possibly because the variable has already been alloced). Is this part of the reason?

Thanks.

A: 

I have a feeling you mean this:

NSArray* a = [NSArray arrayWithObjects:@"foo", @"bar", nil];

and this

NSArray* a = [[NSArray alloc] initWithObjects:@"foo", @"bar", nil];
//...
[a release];

With the first style, the static method performs an alloc/init/autorelease on it for you so you don't have to. With the second style, you have more control over when the memory is released instead of automatically releasing when you exit the current block.

slf
A: 

That code will crash your application. The second version only copies the pointer then releases the instance. You need to call [object retain] before releasing the reference.

Nick Bedford
+1  A: 

This is an idiom used in mutators (sometimes called "setters"), but I think you typed it slightly wrong. Usually it looks like this:

-(void)setMyName:(NSString *)newName
{
    [newName retain];
    [myName release];
    myName = newName;
}

The new name is retained, since this instance will need to keep it around; the old name is released; and finally the instance variable is assigned to point to the new name.

dcrosta
A: 

If myArray is a property and it's set to retain or copy (as it should be for a property like this), then you'll end up double-retaining the variable when you do this:

self.myArray = [[NSArray alloc] init];

The alloc call sets the reference count to 1, and the property assignment will retain or copy it. (For an immutable object, a copy is most often just a call to retain; there's no need to copy an object that can't change its value) So after the assignment, the object has retain count 2, even though you're only holding one reference to it. This will leak memory.

I would expect to see either a direct assignment to the instance variable

myArray = [[NSArray alloc] init];

Or proper handling of the retain count:

NSArray *newArray = [[NSArray alloc] init];
self.myArray = newArray;
[newArray release];

Or the use of autoreleased objects:

self.myArray = [[[NSArray alloc] init] autorelease]; // Will be released once later
self.myArray = [NSArray array]; // Convenience constructors return autoreleased objects
Alex
Thanks for the answer, it cleared some things up for me.
nevan