views:

658

answers:

2

This is unmodified code from Apple's iPhone 'Utility Aplication' template:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

 MainViewController *aController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
 self.mainViewController = aController;
 [aController release];

 mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
 [window addSubview:[mainViewController view]];
 [window makeKeyAndVisible];

}

When mainViewController is assigned to aController, the self keyword is specified:

 self.mainViewController = aController;

However, when the mainViewController's frame is set, the self keyword is not required:

 mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;

If I remove the self keyword from the first example, the program crashes with the message:

objc[1296]: FREED(id): message view sent to freed object=0x3b122d0

If I add the self keyword to the second example, the program runs fine.

Can anyone explain why self is needed in the first case but not the second? I'm assuming that in both cases mainViewController is referring to the same instance variable.

+6  A: 

Using self causes your class' "setter" for this variable to be called, rather than changing the ivar directly.

self.mainViewController = aController;

is equivalent to:

[self setMainViewController:aController];

On the other hand:

mainViewController = aController;

just changes the mainViewController instance variable directly, skipping over any additional code that might be built into UIApplication's setMainViewController method, such as releasing old objects, retaining new ones, updating internal variables and so on.

In the case where your accessing the frame, you're still calling a setter method:

mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;

expands to:

[[mainViewController view] setFrame:[[UIScreen mainScreen] applicationFrame]];

Ideally, to future proof your code, you should also be using self.mainViewController (or [self mainViewController]) when retrieving this value too. In general, classes are much less likely to have important code in their "getter" methods than their "setters", but it's still possible that accessing directly could break something in a future version of Cocoa Touch.

Tobias Cohen
If you're accessing the ivar directly from *within* a class, I don't see how any future updates could break that. It's still a good principle to use the accessor to avoid hassle if you need to refactor the code, but in simple cases I don't think it's a problem if classes access their own ivars directly when getting the value. For setting, I always use the setter method.
Felixyz
You should always use self except inside the getter and setter methods themselves (if you write your own.) That way your object retention is handled automatically for you. You can also provide custom code to do things such validate the iVar or to keep if from ever being nil. Outside of the getter and setter methods, there is seldom if ever any good reason to access the iVar directly. Although, many people do usually out of error or laziness.
TechZen
+2  A: 

the self keyword indicates that you are using the property getter/setter instead of accessing the value directly. in case you let the getter/setter be auto-generated using synchronize you have to use self in the first example because the object is retained there instead of simply pointer-assigned.

Russo