ObjectiveCAnnotate – Simple Annotations for ObjectiveC

Today I’m open sourcing a project that we’ve been using at IdeaSwarm in one incarnation or another for about a year and a half. It’s called ObjectiveCAnnotate.

ObjectiveCAnnotate is a parsing/code-generation project written for and in Objective-C that saves us from writing a lot of boiler plate code from day to day. I hope that others find it useful.

The Problem

I came to Objective-C from Ruby. The first time I saw the @property syntax I expected it to be roughly the same at the attr_accessor syntax in Ruby; that is, I expected it to declare everything that I needed for working with a property.

I was quickly disabused of that notion. In order to get a property working you have to:

  • declare the member variable
  • add the @property syntax in the @interface
  • synthesize the property
  • release it if necessary, depending on the type

This struck me as very repetitive and I quickly grew tired of updating four places in my code each time that I decided to change a variable name. So I wrote some code to make my life easier.

My Solution

I built a little script that parses annotations, which are little bits of meta-data added to header and class files using comments, and outputs the boilerplate code that I’d come to know and love.

I’ve been using the Ruby version of this project for about a year and a half and over that time I’ve added other features:

  • declaring dynamic properties
  • externalizing methods in the header file and keeping the header and implementation in sync
  • private methods and properties

A Quick Example

Say you have a header file:

@interface Truck <NSObject>
{
    BOOL isShiny;
    NSString *licenseNumber;
}

@property (nonatomic) BOOL isShiny;
@property (nonatomic, retain) NSString * licenseNumber;
- (void) runSirens;
@end

@implementation Truck

- (void) runSirens
{
    //do something
}

@synthesize isShiny;
@synthesize licenseNumber;

- (void) dealloc
{
    [licenseNumber release];

    [super dealloc];
}   
@end

If you change any of the properties you have to update the associated statements. If you change the method signature you have to update it in the header file.

Using ObjectiveCAnnotate you have to type:

//@generate

@interface Truck <NSObject>
{
    //@properties
    BOOL isShiny;
    NSString *licenseNumber;
}

@end

@implementation Truck

//@extern
- (void) runSirens
{
    //do something
}

- (void) dealloc
{
    [self generatedDeallocForTruck];
    [super dealloc];
}   
@end

Now any properties that you add get declared and synthesize automatically, and if necessary they are released in the generated dealloc method that you call from the dealloc. Any change to the method signature is automatically reflected in the header file.

For now this is implemented by adding code in generated blocks to the source file. It adds some noise and the file ends up looking like the below:

@interface Truck <NSObject>
{
    BOOL isShiny;
    NSString *licenseNumber;
}

//generated block
@property (nonatomic) BOOL isShiny;
@property (nonatomic, retain) NSString * licenseNumber;
- (void) runSirens;
//end generated block
@end

@implementation Truck

- (void) runSirens
{
    //do something
}

//generated block
@synthesize isShiny;
@synthesize licenseNumber;

- (void) generatedDeallocForTruck
{
    [licenseNumber release];
}
//end generated block

- (void) dealloc
{
    [self generatedDeallocForTruck];

    [super dealloc];
}   
@end

Now any time you add or remove a property or change the method signature you make that change in one place and it is reflected everywhere.

The property syntax is flexible, handling object and non-object types, allowing overriding of property attributes (nonretain, copy, assign, etc), dynamic properties, private properties, etc.

It would be nice if there was a way of handling this that added somewhat less noise than the original syntax, but we’ve settled for being easier to develop with. I’ve tried a few other ways of implementing this and they’ve all fallen short one way or another.

Agh! A Rewrite!

I presented the framework at my local MN CocoaHeads a couple of weeks ago and someone asked if I’d ever thought of re-writing it in Objective-C. My answer was a pretty stern no.

Then I got to thinking. I was already planning on open sourcing the project at some point. It made a lot of sense to open source it in the language that it was working with. That would make it much easier for users to extend. How long could it take to re-write, considering that I already knew the code and requirements ? Ahh, estimates.

Turns out it took about a week and a half to re-write my Ruby script in Objective-C, document it, etc. I made a few improvements on the way, such as block property declarations and the like.

License

ObjectiveCAnnotate is released under a BSD license. That’s just the framework, your code belongs to you.

Get the Bits

Get it from bitbucket: ObjectiveCAnnotate

Documentation and how-to are on that site as well.

Feedback

File bugs: Bug Tracker

Google Group: Google Group

Comments are closed here while I figure out a little spam problem, so please use the group. If it becomes a problem there I’ll have to move to approving members individually, but it uses open enrollment for now.


Comments are closed.