The Joys Of Objective-C and Interface Builder

January 14, 2009

For the last couple months I worked on an iPhone game using only OpenGL, partly to learn it, and partly because I had no experience with Interface Builder. After getting much of it working I decided 9 days ago to take a break and work up an interface for my second game and use the native UI.

9 days later the game is virtually complete, other than creating some game data (and finishing the editor for it). The other game will also get a rewrite in the same fashion (but it's slipped to #3 in the schedule now).

My experience with Objective-C was back in the late 90's when the company I worked for used WebObjects, and before Java was an option (I became the first person in the company to use Java, and then J2EE), but I'd never dealt with desktop applications so I never used IB.

For those who don't know what IB is, its a GUI builder tool. Big deal, eh, lots of those. This one is way better than any I've ever used, partly due to its long history going back to the early 90's, and partly due to the interesting features that Objective-C and the frameworks (first NextStep's and now Cocoa and Cocoa Touch) allow. For all the ancientness of Objective-C as a language, as you get comfortable with it you begin to see a lot of amazing features coming from its SmallTalk-like background.

With IB, you "wire" up objects together, basically creating connections called "Outlets" and actions called "Actions". It comes with many prewired objects that you can drag and connect together. It also is integrated tightly with XCode and your own source code, so the connections are two-way. You save the interface in something called a "NIB" which at runtime is loaded and all the connections wired up for you.

The magic comes from the ease at which you can put together your applications interface, and take advantage of all the useful functionality with very little code. Despite not knowing too much of IB or the frameworks I've written a complete, fairly complex iPhone game in 9 days. All I wanted to do was experiment with an idea, and it grew into the whole app.

As an example here is the entire controller class for my Menu page:

@implementation MenuViewController

- (void)viewWillAppear:(BOOL)animated
{
  puzzlePicker.pickedPuzzle = GAME.gameNumber;
}

- (IBAction)pickPuzzle:(id)sender
{
  [GAME loadGameWithNumber:puzzlePicker.pickedPuzzle];
}

- (IBAction)returnToPuzzle:(id)sender
{
  [self dismissModalViewControllerAnimated:TRUE];
}

- (IBAction)showAbout:(id)sender
{
  [self presentModalViewController:aboutView animated:YES];
}

- (IBAction)showHelp:(id)sender
{
  [self presentModalViewController:helpView animated:YES];
}

- (IBAction)solvePuzzle:(id)sender
{
  [GAME showSolution];
  [self dismissModalViewControllerAnimated:TRUE];
}

@end

Not much to it, yet it does quite a bit of work in those few methods.

Compared to all the work I was doing in OpenGl, this is nothing. As I was working in OpenGL (for a 2D game) I kept thinking how stupid it was to do everything myself and get nothing of the benefits of the native interface. Not to knock OpenGL; for many games it's the only choice. It was also a great learning experience so the time wasn't wasted (I build a wrapper state machine to make OpenGL easier to work with).

This was just ... so fun. All of the 5 remaining apps will be built the same way, even though they do have unique features I can see a lot of similarities in how I have constructed this one.

The game file editor that most of them share is written in Mac Cocoa as it's only used by me, which got me to learn IB and realize how cool it is to work with. Not all of the frameworks and API's are perfect, and sometimes the documentation sucks horribly. And of course XCode is the suckiest IDE on the planet, but the coding has been very productive, and that's what counts.