Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
When creating a new project in Xcode 4, the boilerplate code adds an underscore character when it synthesizes the ivars in the implementation file as:
@synthesize window = _window;
or:
@synthesize managedObjectContext = __managedObjectContext;
Can someone tell me what is being accomplished here? I'm not a complete nube, but this is one aspect of objective-C I don't understand.
Another point of confusion; in the app delegate implementation, after synthesizing the window iVar as above, in the application didFinishLaunchingWithOptions: method the window and viewController ivars are referred to using self:
self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];
but in the dealloc method it's _window, or _viewController
Thanks
This is an artifact of a previous version of the Objective-C runtime.
Originally, @synthesize
was used to create accessors methods, but the runtime still required that instance variables had to be instantiated explicitly:
@interface Foo : Bar {
Baz *_qux;
}
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
People would prefix their instance variables to differentiate them from their properties (even though Apple doesn't want you to use underscores, but that's a different matter). You synthesize the property to point at the instance variable. But the point is, _qux
is an instance variable and self.qux
(or [self qux]
) is the message qux
sent to object self
.
We use the instance variable directly in -dealloc
; using the accessor method instead would look like this (though I don't recommend it, for reasons I'll explain shortly):
- (void)dealloc {
self.qux = nil; // [self setQux:nil];
[super dealloc];
}
This has the effect of releasing qux
, as well as zeroing out the reference. But this can have unfortunate side-effects:
qux
, which are recorded when an accessor method is used to change it.nil
-messaging semantics, however, you'll never know, having used the accessor to set to nil
. Had you released the instance variable directly and not zeroed-out the reference, accessing the deallocated object would have caused a loud EXC_BAD_ACCESS
.Later versions of the runtime added the ability to synthesize instance variables in addition to the accessor methods. With these versions of the runtime, the code above can be written omitting the instance variables:
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
This actually synthesizes an instance variable on Foo
called _qux
, which is accessed by getter and setter messages -qux
and -setQux:
.
I recommend against this: it's a little messy, but there's one good reason to use the underscore; namely, to protect against accidentally direct ivar access. If you think you can trust yourself to remember whether you're using a raw instance variable or an accessor method, just do it like this instead:
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux;
- (void)dealloc {
[qux release];
[super dealloc];
}
@end
Then, when you want to access the instance variable directly, just say qux
(which translates to self->qux
in C syntax for accessing a member from a pointer). When you want to use accessors methods (which will notify observers, and do other interesting things, and make things safer and easier with respect to memory management), use self.qux
([self qux]
) and self.qux = blah;
([self setQux:blah]
).
The sad thing here is that Apple's sample code and template code sucks. Never use it as a guide to proper Objective-C style, and certainly never use it as a guide to proper software architecture. :)