Objective-C Accessors
I like Objective-C. It’s a nice language. However, having to write accessor methods all day is boring, error-prone, and a pain in the ass:
- (NSFoo*) foo{ return foo;}- (void) setFoo:(NSFoo* newFoo){ [foo autorelease]; foo = [newFoo retain];}I mean, c’mon. This is Objective-C we’re talking about, not Java or C . However, until Objective-C 2.0’s property support hits the streets (which, unfortunately, will only be supported on Mac OS X 10.5 and later as far as I know), you really have to write these dumb-ass accessors to, well, access properties in your objects correctly. You don’t need to write accessors thanks to the magic of Cocoa’s Key-Value Coding, but it just feels wrong to access instance variables using strings as keys. I mean, ugh—one typo in the string and you’ve got yourself a problem. Death to dynamic typing when it’s totally unnecessary.
As such, I got totally fed up with this and wrote a little script to generate accessor methods. I’m normally not a fan of code generation, but in this case, the code generation’s actually designed to be one-shot, and it doesn’t alter the ever-picky build process. It’s meant to be used in Xcode, although you can run it via the commandline too if you like.
Given the following input:
int integerThing;NSString* _stringThing;IBOutlet NSWindow* window;It will spit out the following:
#pragma mark Accessors- (int) integerThing;- (void) setIntegerThing:(int)anIntegerThing;- (NSString*) stringThing;- (void) setStringThing:(NSString*)aStringThing;- (NSWindow*) window;- (void) setWindow:(NSWindow*)aWindow;%%%{PBXSelection}%%%#pragma mark Accessors- (int) integerThing{ return integerThing;}- (void) setIntegerThing:(int)anIntegerThing{ integerThing = anIntegerThing;}- (NSString*) stringThing{ return _stringThing;}- (void) setStringThing:(NSString*)aStringThing{ [_stringThing autorelease]; _stringThing = [aStringThing copy];}- (NSWindow*) window{ return window;}- (void) setWindow:(NSWindow*)aWindow{ [window autorelease]; window = [aWindow retain];}There’s a couple of dandy features in the script that I find useful, all of which are demonstrated in the above output:
- It will detect whether your instance variables start with a vowel, and write out
anInteger
instead ofaInteger
as the parameter names for the methods. - It will
copy
rather thanretain
value classes such as NSStrings and NSNumbers, as God intended. - For all you gumbies who prefix your instance variables with a leading underscore, it will correctly recognise that and not prefix your accessor methods with an underscore.1
- IBOutlet and a few other type qualifiers (
__weak
,__strong
,volatile
etc) are ignored correctly. - It will emit Xcode-specific
#pragma mark
places to make the method navigator control a little more useful. - It will emit Xcode-specific
%%%{PBXSelection}%%%
markers so that the accessor methods meant to go into your.m
implementation file are automatically selected, ready for a cut-and-paste.
Download the objc-make-accessors
script and throw it into your “~/Library/Application Support/Apple/Developer Tools/Scripts” folder. If you don’t have one yet:
Done. You should now have a Scripts menu in Xcode with a new menu item named “IVars to Accessor Methods”. Have fun.
1 Note that older versions of the Cocoa Coding Guidelines specified that prefixing instance variables with underscores is an Apple-only convention and you should not do this in your own classes. Now the guidelines just don’t mention anything about this issue, but I still dislike it because putting underscores every time you access an instance variable really lowers code readability.