views:

184

answers:

5

As far as I know, the first one you have to release when you are done, and the second one you don't. Why would you use the first initialization over the second?

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"title", @"text", nil];

And

NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"title", @"text", nil];
A: 

The first init method is an instance method (works on the instance returned by [NSMutableDictionary alloc]) and is not an autoreleased object, with a retain count of 1.

The second is a class method, and returns an autoreleased object (with essentially no retain count).

jbrennan
+2  A: 

You are correct; with the first version, you will need to explicitly release the object. The first version is useful if you will be assigning it to an instance variable in your class; i.e. it is a dictionary that will live beyond the current UI event (the latter object is autoreleased and is not available later on in your program).

For example:

-(id)init
{
    if (self = [super init])
    {
        myDict = [[NSDictionary alloc] init ...];
    }
    return self;
}

-(void)dealloc
{
    [myDict release];
    [super dealloc];
}
Jason
A: 

The second one is auto released by the NSMutableDictionary class where as the first one you handle your own memory management.

James Raybould
A: 

Read the memory management rules. 9 short paragraphs, you can read in about a minute. They clearly explain the difference between the two.

As to why you should use one or the other, it depends on the platform.

On the iPhone, which is under powered and low on memory, you would generally prefer the former unless you are going to be forced to use autorelease (for example, if you are going to return it from a method whose name does not begin with “alloc” or “new” or contains “copy”). If you are going to autorelease it, then use the second form. Otherwise, use the first form and release it explicitly yourself in the method.

On the Mac, which has more than enough power and memory to make the autorelease pool a trivial detail (in all but the most pathelogical cases), you can use the second form for any case. Normally if you are going to keep it around you would assign it to a copy/retain property so you would not need to retain it. The exception is in an init method, where you can't use setters, or in setters you are implementing manually, and thus need to assign to the ivar yourself. In those cases you would often use the former.

But all of that is just style/premature optimization (not necessarily bad in this case, since in is a low level noise kind of optimization that profiling will not detect and that will just generally slow you app down by a little). The important thing is to read the rules and follow what they say, and if you do that, you can use either form as you please.

Peter N Lewis
+2  A: 

As others have said, in one sense there is no difference between your two examples, just that the first one returns a retained object that will not be dealloc'd until you expicitly release it, and the second one is an autoreleased object that will be automatically released at the beginning of the next run loop unless you explicitly retain it before then.

However the key part to your question is:

Why would you use the first initialization over the second?

The commonly regarded approach (support by Apple documentation) is that using autoreleased objects is absolutely fine in most cases. I would not agree with Peter Lewis here about the iPhone being so "underpowered" that you need to avoid autoreleased objects. The additional overhead on the phone on supplying autoreleased objects in most apps is miniscule. Therefore feel free to use autoreleased objects generally in your code, and just explicitly retain them if you need to hang on to them.

However, where it does make a difference is in tight loops. If you are running a while loop for example which executes 1000 times, and you are creating objects within that loop that you will not need afterwards, then you should explicitly create new non-autoreleased objects and explicitly release them. This is because the autorelease pool will not (by default) empty inside the tight loop. Creating a large bunch of autoreleased objects could well start to hit the limitations of the device's memory.

So in summary; use 2) most of the time, but use 1) if you're going to be creating and ditching a lot of objects at one time.

Hope that helps

h4xxr
+1 for mentioning the special beasts that are tight loops. I would like to add that if you're using a lot of library calls in a tight loop which use autoreleased objects themselves, you can create and destroy an NSAutoreleasePool for each iteration of the loop. This isn't costly at all and could stop potentially nasty memory bloat.
Toon Van Acker
Yes spot on Toon. I did think of mentioning this but decided my post was long enough!
h4xxr