tags:

views:

298

answers:

3

There are a lot of cases in which one would alloc an instance, and release it right after it's being assigned to something else, which retains it internally.

For example,

UIView *view = [[UIView alloc] initWithFrame...];
[self addSubView:view];
[view release];

I have heard people suggesting that we go with autorelease rather than release right after.

So the above becomes:

UIView *view = [[[UIView alloc] initWithFrame...] autorelease];
[self addSubView:view];

What's the best practice here? Pros and cons?

+6  A: 

In most cases, it wont really matter either way. Since -autorelease simply means that the object will be released at the end of the current iteration of the run loop, the object will get released either way.

The biggest benefit of using -autorelease is that you don't have to worry about the lifetime of the object in the context of your method. So, if you decide later that you want to do something with an object several lines after it was last used, you don't need to worry about moving your call to -release.

The main instance when using -release will make a noticeable difference vs. using -autorelease is if you're creating a lot of temporary objects in your method. For example, consider the following method:

- (void)someMethod {
    NSUInteger i = 0;
    while (i < 100000) {
        id tempObject = [[[SomeClass alloc] init] autorelease];

        // Do something with tempObject

       i++;
    }
}

By the time this method ends, you've got 100,000 objects sitting in the autorelease pool waiting to be released. Depending on the class of tempObject, this may or may not be a major problem on the desktop, but it most certainly would be on the memory-constrained iPhone. Thus, you should really use -release over -autorelease if you're allocating many temporary objects. But, for many/most uses, you wont see any major differences between the two.

Matt Ball
+1. autorelease gets a lot of flak over performance (flak I've seldom seen backed up with numbers in normal, non-large-loop code), but autorelease also saves a lot of leaks when code gets refactored. I do use release more often in low-level routines since I don't know whether they might be called in a large loop at a higher level. If you're going to use release, though, you really must set the variable to nil immediately afterwards if the variable will still be in scope. Never release an object but still have a pointer to it.
Rob Napier
+1  A: 

I agree with Matt Ball. Let me just add that, if you find yourself using this pattern frequently, it can be handy to write a quick category:

@interface UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame;
@end

@implementation UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame
{
    UIView * newView = [[viewType alloc] initWithFrame:frame];
    [self addSubView:newView];
    return [newView autorelease];
}
@end

Which can be used as follows:

UIView * view = [someView addNewSubviewOfType:[UIView class]
                                      inFrame:someFrame];

And it even works with other types, as long as they are derived from UIView:

UIButton * button = [mainView addNewSubviewOfType:[UIButton class]
                                          inFrame:buttonFrame];
e.James
+1  A: 

I usually go for -release rather than -autorelease whenever possible. This comes from years of experience debugging and enhancing other people's Objective-C code. Code that uses autorelease everywhere makes it harder to debug when an object gets over-released, since the extra release happens far away from the incorrect code.

It's also the case that many folks use autorelease when they just don't understand how cocoa memory management works. Learn the rules, learn the API, and you'll almost never need to autorelease an object.

A last minor point is that if you don't need the autorelease behavior, then using autorelease just needlessly adds extra work for your program to do.

Mark Bessey