views:

137

answers:

3

What reasons are there for doing in three lines what could be done in one?

Here is some code from developer.apple.com:

UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

self.navigationController = aNavigationController;

[aNavigationController release];

...and the same thing in one line:

self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

It seems clean, simple, and straightforward enough. I've had trouble in the past with a property not being retained, causing [object release] to destroy the object when it wasn't supposed to (so far as I could tell - the retain attribute was set). Using the one-line formula works like a dandy.

A: 

Most properties of Objective-C object types should be declared with retain or copy in their declarations. For instance, you might say:

@property (retain) UINavigationController * navigationController;

If that's the case, the automatically written setNavigationController function will call retain for you, and the one-liner would be:

self.navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];

You may be running into problems if the property you're setting uses (assign) instead of (retain) or (copy). In that case, the setter just makes its pointer equal to the other pointer, and a subsequent release of the object would cause it to be cleaned up.

You may also have problems if you were calling release instead of autorelease.

Hope that helps!

Ben Gotow
+6  A: 

The Objective-C memory management rules dictate that by allocing an object instance you are a (shared once other objects retain it) owner of that instance and so you must release the UINavigationController when you want to relinquish ownership to prevent a memory leak. In a non-garbage collected environment (e.g. on the iPhone) this means balancing alloc or copy (or methods that contain "alloc" or "copy") with release or autorelease. Your second snippet would then be

self.navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];

If you can avoid using autorelease on a memory-limited environment (like the iPhone), it's better to use explicit release. -[NSObject autorelease] adds the receiver to the current NSAutoreleasePool which will subsequently call -release on the objects in the pool 'some time in the future.' When you want to be careful about memory usage, 'some time in the future' is not a good idea. Thus, on the iPhone your first example is the standard usage.

Barry Wark
In that case, is the problem: when self is released by its owner, UINavigationController is not?
JoBu1324
Barry is exactly correct - read the rules he mentioned. The problem is that you alloc it, so you must release it. The navigationController property will itself retain and release it as necessary. You are correct that if you don't release it (as you did in your second example) then the UINavigationController will never be released and will leak, even after self is released.
Peter N Lewis
A: 

Depending on how you defined your property there you have a memory leak. Pretty much any time you see an alloc/init combo you are getting back an object with a reference count of one. Assuming your property is defined as retain (which it probably should be) then setting the property will increment the reference count to two.

If you really want to keep it all on one line go with something like this:

self.navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];

Although even that is recommended against as autoreleasing objects can cause them to be around for longer than needed.

Lounges
-autorelease simply means send this object -release later. Using -autorelease in this situation will not cause the navigation controller to stick around longer than needed because it is already sticking around - we are assigning to our ivar.
Jim Correia
Right... autorelease simply add's a reference to the object in the current autorelease pool. That does cause it to stick around longer (not in this situation) because you must wait for the pool to be drained to actually free the object. In this situation (since the object is being retained it doesnt matter, however its not a good habit to get in to autorelease objects in this fashion.
Lounges