Search code examples
objective-ciosmemory-managementsimplification

Why does iPhone sample code use so many intermediate variables?


I'm currently working through Apress's "Beginning iPhone 3 Development". A standard they use in their example applications is like the following code:

- (void)viewDidLoad {
    BlueViewController *blueController = [[BlueViewController alloc] 
                                         initWithNibName:@"BlueView" bundle:nil];
    self.blueViewController = blueController;
    [self.view insertSubview:blueController.view atIndex:0];
    [blueController release];
}

8.14.11 UPDATE (additional information)
blueViewController is declared as follows:

@property (retain, nonatomic) BlueViewController *blueViewController;

Whenever they perform an alloc they put it in some temp variable (here blueController) then they assign it, then they release it. This temp variable seems superfluous to me.
I simplified the code as follows:

- (void)viewDidLoad {
    self.blueViewController = [[BlueViewController alloc] 
                              initWithNibName:@"BlueView" bundle:nil];
    [self.view insertSubview:blueViewController.view atIndex:0];
}

- (void)dealloc {
    [blueViewController release];
    [super dealloc];
}

My modified code ran just the same in the iPhone simulator. Now, I know the rule that if you alloc something you need to release it. And I'm covering that in my dealloc method. But is there some advantage to having a release directly in the ViewDidLoad (the function where the alloc was called)? Or is it equally ok to have a release in your dealloc method like this?
Thanks for any help,
-j


Solution

  • Assuming blueViewController is a retain property, the temporary variable is not superfluous. Your simplification is creating a memory leak. This statement from the second snippet leaks:

    self.blueViewController = [[BlueViewController alloc] 
                              initWithNibName:@"BlueView" bundle:nil];
    

    In terms of ownership, you own the object returned by alloc-init and then the property accessor claims ownership of the object again, resulting in the object being over-retained.

    Using a temporary variable solves this problem. Another option is to use autorelease:

    self.blueViewController = [[[BlueViewController alloc] 
                              initWithNibName:@"BlueView" bundle:nil] autorelease];
    

    Note that after this statement you effectively own the object and you must release it in dealloc.


    You did not mention how the property blueViewController is declared. Anyway, whatever the semantics of the setter are (retain, copy, assign), that statement is wrong. I already explained the most likely scenario: retain. Let's have a look at the other two possibilites (without considering if they make sense at all):

    • If blueViewController happened to be a copy property, the statement would leak too. The property accessor copies the original object and now the property holds a pointer to the copy and you lost track of the original object, immediately leaking it.

    • The least likely scenario is that blueViewController is an assign property because this is most likely wrong and you really want retain. But, anyway, the assign properties are for objects you do not own, e.g. delegates, and you are not supposed to release them. You are assigning an object you own to it, so either you leak it or you incorrectly release the assign property.