Tuesday, June 2, 2009

Runtime Madness

There was a fascinating discussion on Twitter this morning regarding the modern runtimes featured on 64-bit Macs and on the iPhone. One of the features of the new runtime is automatic creation of instance variables for your properties. So, for example, this is a perfectly valid class for 64-bit Mac programs:

#import <Cocoa/Cocoa.h>

@interface TestController : NSObject {

}

@property (retain) NSString *testString;
@end


Notice that there's no instance variable declaration for testString; it's not needed. Now that the fragile base class problem has been eliminated in the modern ABI, the runtime is capable of doing this work for us.

This works on the iPhone also. Unfortunately, though, the iPhone simulator is a 32-bit Mac application, which means programs running in the simulator cannot take advantage of this feature. In other words, the following class is a perfectly valid class when compiled for the iPhone device, but will fail with errors when compiled against the simulator:

#import <UIKit/UIKit.h>

@interface HeroEditViewController : UITableViewController {
}

@property (nonatomic, retain) NSManagedObject *myObject;
@end


You could use this feature on the iPhone, but not on the simulator by doing this:

#import <UIKit/UIKit.h>

@interface HeroEditViewController : UITableViewController {
#if TARGET_IPHONE_SIMULATOR
NSManagedObject *myObject;
#endif
}

@property (nonatomic, retain) NSManagedObject *myObject;
@end



But, there's a catch. The modern ABI doesn't allow access to @private instance variables, and the instance variables created for you by the runtime are @private. That means you cannot access the underlying, undeclared instance variable from within your own class. You have to use the accessor method everywhere.

So, what's the advantage of not declaring the underlying instance variable? If you're writing a 64-bit Mac application, it can save you a fair bit of typing. On the iPhone, it doesn't save you any typing at all, in fact, it adds two lines of code unless you never, ever use the simulator. That means that for most iPhone developers, there really is no advantage to using feature right now. In the future, it is possible, and maybe even likely that there will be compiler optimizations that can happen only if you've you've let the runtime create your instance variables for you, however.

Craig Hockenberry has opened a bug report to request that the iPhone simulator be changed to use a modern runtime (without changing the datatype sizes to 64-bit sizes, of course). If you'd like to be able to have your instance variables synthesized, you might want to dupe his report. The more developers who report a specific bug or feature request, the more likely Apple is to look at implementing the requested fix or feature.

If you're wondering if you should use this new feature in your iPhone applications, there's really no one answer. There's absolutely no guarantee that there will ever be any advantage to using this on the iPhone. Unless you don't use the simulator at all, you still have to declare the instance variables when compiling for the simulator, so it doesn't save you any typing. It's a gamble, so feel free to use it you want, but there's certainly no compelling reason to use it yet.

I would, though, start moving away from direct instance variable access when using properties. At some point, it will probably make sense to use this feature, and you'll be stuck updating a lot of code if you directly access your instance variables.

Thanks to @bbum, @borkware, @chockenberry and the rest of the Cocoa geeks who participated in the educational discussion!

Note: If you want to experiment with this on a Mac program, here are the configuration options in Xcode's project you'll need to change so that you're not also building a 32-bit version (for which the instance variables can't be synthesized) - click for larger versions (there are two pictures):


No comments:

Post a Comment