Thursday, July 1, 2010

Synthesize by Default

So, in my previous post, I told you I was excited about the "synthesize by default" functionality that's now available in LLVM 1.5. And I am, very much so. But it turns out there's a caveat that tempers my excitement at the moment.

With synthesized iVars, we've had direct access to the underlying synthesized variable for a while now, so if you created a class like this:

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController

@property (nonatomic, retain) NSString *foo;

You're able to access the NSString variable foo that backs the property of the same name within the scope of your class. So, in your dealloc method, you can do this, to give one common example:

- (void)dealloc
[foo release], foo = nil;
[super dealloc];

However, if you enable the "synthesize by default" feature in LLVM 1.5 and use it, meaning you don't actually have a @synthesize statement for the foo property, you lose this direct access to the underlying variables, leaving you with a bit of a conundrum - how do you do your memory cleanup without unintentionally triggering unwanted functionality, such as those in a lazy accessor or some more involved mutators.

Earlier today, I tweeted a question asking about the correct way to deal with this situation. After a bit of a Who's on First-like back and forth with many smart people, it finally came out that this is a bug in LLVM, not an intentional design decision. Hopefully it will be fixed before too long, but in the meantime, the best answer is probably to just keep using @synthesize.

Thanks to a whole bunch of people on Twitter, many of whom I'm sure I missed!


Daniel said...

[foo release], foo = nil;

i have never seen this befor..
Is it the same as

[foo release]; foo = nil;

or a typo?

MarkDalrymple said...

It's legal C. The comma operator separates expressions in a single statement.

Here it's being used as programmer-to-programmer communication. "These two expressions are cleaning up foo, so think of them as a unit." Execution-wise, they're identical.

Vargo said...

I find it very frustrating that you need to explicitly synthesize with a backing variable in order for your project to compile in the Simulator. Is this still the case? I really wish there were a way around this, so I can compile the same code in the simulator as the device and not have to explicitly write:
@synthesize myProperty=_myProperty;

Louis said...

Vargo: the SDK 4 is apparently shipping as using the modern runtime. So you should be able to get rid of the ivar!