views:

319

answers:

6

Given the two scenarios, which code is best practice and why?

Autorelease

loginButton = [[[UIBarButtonItem alloc] initWithTitle:@"Login" 
                                                style:UIBarButtonItemStylePlain 
                                                target:self 
                                                action:@selector(loginButtonClicked:)]
                                                autorelease];
self.navigationItem.rightBarButtonItem = loginButton;

or

Release

loginButton = [[UIBarButtonItem alloc] initWithTitle:@"Login" 
                                                style:UIBarButtonItemStylePlain 
                                                target:self 
                                                action:@selector(loginButtonClicked:)];
self.navigationItem.rightBarButtonItem = loginButton;
[loginButton release];
+5  A: 

For your example, it doesn't really matter. Personally, I would probably use the first case. That would let you add modifications or debugging code later without having to worry about moving the [loginButton release] line around.

Carl Norum
Any explanation for the downvote?
Carl Norum
No idea, probably just someone who feels strongly enough that autorelease is somehow evil in all cases on the iPhone. I give you +1 because you're actually considering the case he posted, not just issuing a blanket statement. And because I feel the same way as you.
Quinn Taylor
+5  A: 

There seems to be a stigma against using autorelease (i.e. prefer to release whenever possible), which is why I typically go the second route. But since you're not in a loop here, releasing now vs. autoreleasing later will have exactly the same effect (since another object has retained loginButton, it won't be dealloc()ed).

But I should point out that most of my memory leaks are caused by forgetting to add the release line, so it would probably be better to just tack on the autorelease right away.

Brian
On a low memory device like an iPhone, it is better to explicitly release, when possible. It also makes debugging weird EXC_BAD_ACCESS errors easier, because an explicit release means you are in control over the object's lifespan.
Alex Reynolds
@Alex, in this case it literally makes no difference - the object is being retained immediately after creation. All that's going to happen is the reference count will be decremented by one... who cares if that happens immediately or sometime later on?
Carl Norum
It makes no difference only if you never reassign self.navigationItem.rightBarButtonItem before the autorelease pool is released.
JeremyP
+2  A: 

Either will be just fine in your case, as Carl says. It is because the UIBarButtunItem object stays in the memory because one reference to it is kept inside self.navigationItem (assuming you declared that property with @property (retain).). Therefore, the usual diatribe against using the autorelease pool, that it keeps unnecessary objects in memory until the end of the current event loop, doesn't apply here.

Yuji
A: 

Since the navigationItem retains it, the two end up being identical. Style-wise, autorelease is preferred for returns from methods that don't say alloc or copy in their name, but otherwise it is up to you. If the object wasn't separately retained, release would free up the memory faster.

The code-style issue of setting a reference to nil after release is a related question.

Jeremy Murray
+1  A: 

Since you're on a very tight memory budget on the iPhone, the preferred way should be through explicit release. This way objects don't stick around until the autorelease pool gets emptied during the runloop and you are able to keep your memory footprint as small as possible.

Claus Broch
This criticism is only valid for temporary "throwaway" objects that won't survive the scope in which they were created. When you're creating an object that's stored long-term, it makes less difference, since the object will still be around whether you release or autorelease. In such cases, it's more a matter of preference.
Quinn Taylor
A: 

When you send an -autorelease message to an object, you're adding it to a list, and it will get a -release message when the autorelease pool is released. The entire purpose of -autorelease is to provide a way for you to balance your retains and releases when something else might still want the object you're releasing, but you don't. In the situation you describe, the second example you gave is better.

NSResponder