Automatic Property Instance Variables with Objective-C

The modern Objective-C runtime includes a great timesaving feature of allowing automatic synthesis of instance variables. This is a great feature but one that I have been reluctant to use (and especially reluctant to teach) as the default implementation of it makes silly mistakes really easy to make.

Take the example of a very simple Person class:

@interface Person : NSObject

@property (retain) NSString *name;

@end
@implementation Person

@synthesize name;

- (void)dealloc
{
  self.name = nil;
  [super dealloc];
}

@end

That all looks good, right? No ivar cluttering up the class interface.

I disagree, the problem with this code is that the ivar that gets generated by default from this code is simply called name and it allows for easy slips with forgetting accessing the ivar directly to be written:

// Direct ivar access bypassing property accessors
name = [NSString stringWithString:@"Dave"];
// Access through synthesized property accessors
self.name = [NSString stringWithString:@"Dave"];

Obviously the memory management implications of these two lines of code are completely different and the first will cause an application to crash whenever the name property is accessed as the autoreleased variable is never retained as the property setter is never called.

I strongly believe that we should make it as hard as possible to make silly mistakes when coding and using implicit ivars with the same names as their properties makes it way too easy to make a mistake like the one above and I always prefix my ivars with an underscore to stop code like that from compiling.

But I would also love to take advantage of the automatic creation of ivars with the modern runtime and until recently I did not think this was possible but it is! You can omit the ivar declaration in the interface and just have a custom synthesize statement to force the automatic synthesis of ivars to use an alternate name for the ivar:

@interface Person : NSObject

@property (retain) NSString *name;

@end
@implementation Person

@synthesize name = _name;

- (void)dealloc
{
  self.name = nil;
  [super dealloc];
}

@end

Any code which attempts to access the name ivar will now cause a compiler error as the ivar is now called _name.

I am not sure it has always worked this way as I am sure I have tried this previously and not had the same results but with the latest Xcode 3/iOS SDK 4.2 this is certainly the state of things now and I have to say I am completely happy with how it works as it gives a good level of safety with only a minor inconvenience of adding a prefixed ivar name to the end of each synthesize statement.

The final thing to note here is that the application templates that ship with the latest beta of Xcode 4 have finally been updated to use this style of property declaration. This is really great news, thank you Apple! I wonder if the bug reports I filed helped get those changed.

Updated: Apparently Apple have recently updated their docs to recommend that underscores are no longer used for property ivars however the technique works just as well with any ivar prefix.

I hope this helps to clear this up for everyone as it has been the subject of a few questions on the course recently.

What we do

Interested in learning how to develop apps for iOS? Check out our training courses.

iOS Dev Weekly

We also run iOS Dev Weekly, a free weekly email with 10 or so links to the best blog posts and articles on iOS development for the week. If you are interested in iOS development then it is likely that you will find something of interest in iOS Dev Weekly each week. You should subscribe!.