Reputation: 18270
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?
Upvotes: 56
Views: 34661
Reputation: 11161
If you're using Xcode, it can help you detect such code with the static analyzer. Just hit Build >> Build and Analyze
This will show you a very helpful message at such pieces of code.
Upvotes: 5
Reputation: 26434
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.
Upvotes: 2
Reputation: 84398
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:
alloc
, it has a reference count of 1.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.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.
Upvotes: 71
Reputation: 8161
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:
Upvotes: 31
Reputation: 8823
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.
Upvotes: 4
Reputation: 75077
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.
Upvotes: 5