I often see something like the following:
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];
self.navigationItem.rightBarButtonItem = anotherButton;
[anotherButton release];
specifically where a local var, in this case 'anotherButton' is used and then later released. Is this exactly the same as autoreleasing it when it is alloc'ed and then making sure it is used before the method ends? i.e.:
UIBarButtonItem *anotherButton = [[[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)] autorelease];
self.navigationItem.rightBarButtonItem = anotherButton;
I ask because I see it done the first way a huge amount of the time, but it feels less error prone (for me) to just autorelease it outright. Is it just a matter of personal style or are there differences to these two approaches apart from one methodically releasing the object after all is done with it, and the other taking care to claim it to be released at the outset so one doesn't accidentally forget to, both having merits.
From Allocate Memory Wisely in Tuning for Performance and Responsiveness Table 7-2 Tips for allocating memory:
Tip
Reduce your use of autoreleased
objects.
Actions to take
Objects released using the autorelease
method stay in memory until you
explicitly drain the current
autorelease pool or until the next
time around your event loop. Whenever
possible, avoid using the autorelease
method when you can instead use the
release method to reclaim the memory
occupied by the object immediately. If
you must create moderate numbers of
autoreleased objects, create a local
autorelease pool and drain it
periodically to reclaim the memory for
those objects before the next event
loop.
When you autorelease something, you add it to a group of objects which will be released at some point in the future. This means that those objects still exist. Since iOS provides a limited amount of memory, it is suggested that you use release over autorelease whenever possible. You don't want your program to crash from low memory because you have a lot of autoreleased objects.
Excellent question. By autoreleasing, you are delaying the automatic release of objects. This is all fine and dandy and expected behavior when you need to return something from a method, but keeping that object in memory longer than is necessary can be impactful to your app.
By releasing it when you are done, you are freeing the resource at that moment and the memory could be used by another object at runtime. In Cocos2D it is standard practice to autorelease nearly everything and things seem to work OK, but it still rubs me the wrong way and I would not do that in general practice.
They accomplish the same thing. Some folks think you should avoid the use of autorelease whenever possible, so strongly prefer the release as soon as you can option. This was discussed here just yesterday.
In the code you cite, the difference between the two really is minimal. It's unlikely that anotherButton
will be deallocated even after it's released because the assignment to self.navigationItem.rightBarButtonItem
probably causes anotherButton
to be retained.
The best argument for calling release as soon as possible, IMO and in this situation, is that by releasing anotherButton
you're explicitly documenting the fact that you're done using it. Also, the static analyzer will ding you if you use anotherButton
after the release. These two facts can help you avoid errors, and just make your code easier to understand.
The argument in favor of autorelease in a situation like this is that it might be marginally easier to read. I think there's a reason that Apple gives us all those convenience methods like +stringWithFormat: -- they let you create and use the string you want with one method rather than three.