Why does the iPhone example code use so many intermediate variables?

I am currently working on Apress "Getting Started Developing iPhone 3". The standard that they use in their examples is similar to 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 execute alloc , they put it in some temporary variable (here blueController ), then they assign it, then they release it. This temporary 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]; } 

The modified code worked exactly the same in the iPhone simulator. Now I know the rule that if you select something, you need to free it. And I talk about this in my dealloc method. But is there any advantage in releasing directly in ViewDidLoad (the function in which alloc was called)? Or is it equally normal to have release in your dealloc method like this?
Thanks for any help
-j

+4
source share
3 answers

Assuming blueViewController is a retain property, a temporary variable is not redundant . Your simplification creates a memory leak. This is a statement from the second leak fragment:

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

In terms of ownership, you are the owner of the object returned by alloc-init, and then the accessor property claims ownership of the object again, resulting in the object not being saved .

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 actually own the object, and you must free it in dealloc.


You did not specify how the blueViewController property is blueViewController . In any case, regardless of the semantics of the setter ( retain , copy , assign ), this statement is incorrect. I have already explained the most likely scenario: retain . Let's look at two other possibilities (without considering whether they make sense at all):

  • If blueViewController is a copy property, the expression also blueViewController . The property accessor copies the source object, and now the property contains a pointer to the copy, and you lost the original object, immediately leaking it.

  • The least likely scenario is that blueViewController is an assign property because it is most likely wrong and you really want retain . But, in any case, you do not have the assign property for objects, for example. delegates, and you should not let them out. You assign your object to it, so either you leak it or you incorrectly release the assign property.

+8
source
 @property (retain) MyCLass *obj; MyClass *tmpObj = [[MyClass alloc] init]; self.obj = tmpObj; [tmpObj release]; 

In the first line, you get ownership through alloc . Then, on line 2, you again get ownership, as the property is saved. On the third line, you release the ownership that you obtained through alloc . Now you have one ownership through the save property, which you can publish in the future, maybe in dealloc .

Now consider what happens if you delete tmpObj .

 self.obj = [[MyClass alloc] init]; 

In this line, you get ownership twice, once through alloc and once through a property. Now [obj release] once is not enough. You need to release it twice to avoid a leak, and, of course, flushing twice is an extremely bad and possible source for further memory leak. If you make another call to self.obj = anotherObj , then you will skip the old one. To avoid this, you will need this temporary pointer.

+3
source

There are two reasons I can think of my head; The first, more specific example, is that you often see similar methods where the blueController is allocated and initialized, and then checked for validity before the self ivar value is assigned. After this template, in each such method it will be easier for you to conduct tests between the creation of an object and its purpose, if you are aware that this should happen. As far as I know, if such an intermediary really remains redundant, the compiler should optimize it.

A second, more general purpose for this pattern in Cocoa is that Obj-C and Cocoa encourage extremely long, detailed method and variable names, so a single method call can span multiple lines; using method calls as direct arguments to other methods can quickly become unreadable, therefore conventions allow you to pre-configure each argument for a method by placing them in intermediate variables, and then use variables as arguments to increase readability and simplify changing one argument without having to dig into nested method calls.

0
source

All Articles