I see a lot of code, particularly in Apple example code, that resembles the following:
EditingViewController *controller = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
self.editingViewController = controller;
[controller release];
Is there any reason in particular that the approach above proves beneficial over:
self.editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
Trying to understand if there is a strategy for the above.
Thanks!
On first glance, it would seem that your example would work, but in fact it creates a memory leak.
By convention in Cocoa and Cocoa-touch, any object created using [[SomeClass alloc] initX]
or [SomeClass newX]
is created with a retain count of one. You are responsible for calling [someClassInstance release]
when you're done with your new instance, typically in your dealloc
method.
Where this gets tricky is when you assign your new object to a property instead of an instance variable. Most properties are defined as retain
or copy
, which means they either increment the object's retain count when set, or make a copy of the object, leaving the original untouched.
In your example, you probably have this in your .h
file:
@property (retain) EditingViewController *editingViewController;
So in your first example:
EditingViewController *controller =
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// (1) new object created with retain count of 1
self.editingViewController = controller;
// (2) equivalent to [self setEditingViewController: controller];
// increments retain count to 2
[controller release];
// (3) decrements retain count to 1
But for your second example:
// (2) property setter increments retain count to 2
self.editingViewController =
// (1) new object created with retain count of 1
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// oops! retain count is now 2
By calling the autorelease
method on your new object before passing it to the setter, you ask the autorelease pool to take ownership of the object and release it some time in the future, so for a while the object has two owners to match its retain count and everything is hunky dory.
// (3) property setter increments retain count to 2
self.editingViewController =
// (1) new object created with retain count of 1
[[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]
// (2) give ownership to autorelease pool
autorelease];
// okay, retain count is 2 with 2 owners (self and autorelease pool)
Another option would be to assign the new object directly to the instance variable instead of the property setter. Assuming your code named the underlying instance variable editingViewController
:
// (2) assignment to an instance variable doesn't change retain count
editingViewController =
// (1) new object created with retain count of 1
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// yay! retain count is 1
That's a subtle but critical difference in the code. In these examples, self.editingViewController = x
is syntactic sugar for [self setEditingViewController: x]
but editingViewController
is a plain old instance variable without any retain or copy code generated by the compiler.
See also Why does this create a memory leak (iPhone)?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With