Why is release often called shortly after a local

2019-07-20 15:37发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.