Object allocate and init in Objective C

Objective CCocoaCocoa TouchMemory Management

Objective C Problem Overview


What is the difference between the following 2 ways to allocate and init an object?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

and

self.aController= [[AController alloc] init];

Most of the apple example use the first method. Why would you allocate, init and object and then release immediately?

Objective C Solutions


Solution 1 - Objective C

Every object has a reference count. When it goes to 0, the object is deallocated.

Assuming the property was declared as @property (retain):

Your first example, line by line:

  1. The object is created by alloc, it has a reference count of 1.
  2. The object is handed over to self's setAController: method, which sends it a retain message (because the method doesn't know where the object is coming from), incrementing its reference count to 2.
  3. The calling code no longer needs the object itself, so it calls release, decrementing the reference count to 1.

Your second example basically does steps 1 and 2 but not 3, so at the end the object's reference count is 2.

The rule is that if you create an object, you are responsible for releasing it when you're done with it. In your example, the code is done with tempAController after it sets the property. It is the setter method's responsibility to call retain if it needs that object to stick around.

It's important to remember that self.property = foo; in Objective-C is really just shorthand for [self setProperty:foo]; and that the setProperty: method is going to be retaining or copying objects as needed.

If the property was declared @property (copy), then the object would have been copied instead of retained. In the first example, the original object would be released right away; in the second example, the original object's reference count would be 1 even though it should be 0. So you would still want to write your code the same way.

If the property was declared @property (assign), then self isn't claiming ownership of the object, and somebody else needs to retain it. In this case, the first example would be incorrect. These sorts of properties are rare, usually only used for object delegates.

Solution 2 - Objective C

As others have noted, the two code snippets you show are not equivalent (for memory management reasons). As to why the former is chosen over the latter:

The correct formulation of the latter would be

self.aController= [[[AController alloc] init] autorelease];

Compared with the former, this adds additional overhead through use of the autorelease pool, and in some circumstances will lead to the lifetime of the object being unnecessarily extended (until the autorelease pool is released) which will increase your application's memory footprint.

The other "possible" implementation (depending on where the example is from) is simply:

aController = [[AController alloc] init];

However, setting an instance variable directly is strongly discouraged anywhere other than in an init or dealloc method. Elsewhere you should always use accessor methods.

This brings us then to the implementation shown in sample code:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

This follows best practice since:

  • It avoids autorelease;
  • It makes the memory management semantics immediately clear;
  • It uses an accessor method to set the instance variable.

Solution 3 - Objective C

Note also that your desire to cut the code down to one line is why many people use Autorelease:

self.aController = [[[AController alloc] init] autorelease];

Though in theory on the iPhone autorelease is somehow more expensive (never heard a clear explanation why) and thus you may want to explicitly release right after you assign the object elsewhere.

Solution 4 - Objective C

If you're using Xcode, it can help you detect such code with the static analyzer. Just hit Build >> Build and Analyze

alt text

This will show you a very helpful message at such pieces of code.

alt text

Solution 5 - Objective C

One other thing to note is that your example depends on the @property definition of aController also.

If it were defined as @property (readwrite, retain) id aController; then your example works, while if it is defined as @property (readwrite, assign) id aController; then the extra call to release would cause your object to be deallocated.

Solution 6 - Objective C

You could also do

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

with a retaining property, and it would function the same way, but its better to use the other way (for retaining properties) because it's less confusing, that code makes it look like you assign aController and then it gets deleted from memory, when actually it doesn't because setAController retains it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRonnie LiewView Question on Stackoverflow
Solution 1 - Objective CbenzadoView Answer on Stackoverflow
Solution 2 - Objective CmmalcView Answer on Stackoverflow
Solution 3 - Objective CKendall Helmstetter GelnerView Answer on Stackoverflow
Solution 4 - Objective CleviathanView Answer on Stackoverflow
Solution 5 - Objective CAshley ClarkView Answer on Stackoverflow
Solution 6 - Objective Cmk12View Answer on Stackoverflow