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:

  1. It will detect whether your instance variables start with a vowel, and write out anInteger instead of aInteger as the parameter names for the methods.
  2. It will copy rather than retain value classes such as NSStrings and NSNumbers, as God intended.
  3. 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
  4. IBOutlet and a few other type qualifiers (__weak, __strong, volatile etc) are ignored correctly.
  5. It will emit Xcode-specific #pragma mark places to make the method navigator control a little more useful.
  6. 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:

mkdir -p ~/Library/"Application Support"/Apple/Developer Tools/Scripts/10-Scripts
ln -sf "/Library/Application Support/Apple/Developer Tools/Scripts/10-User Scripts/99-resetMenu.sh" ~/Library/"Application Support"/Apple/Developer Tools/Scripts/10-Scripts/
cp ~/Desktop/objc-make-accessors ~/Library/"Application Support"/Apple/Developer Tools/Scripts/10-Scripts/

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.

blog comments powered by Disqus