Code Example: Drawing the iPhone Back Button

Recently, I had need to provide a back button similar to the one used in Mobile Safari for a consulting project.

Many of the buttons used in the built-in iPhone applications are made available via the SDK with built in button types and graphics. Unfortunately, the back button is not one of these.

Because I needed to display the toolbar button from inside a static library which can not include images, I had to render the back arrow directly in code.

Since this was a bit time consuming, I thought I would share in hopes that it saves someone else a little bit of time.

- (CGContextRef)createContext
{
   // create the bitmap context
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = CGBitmapContextCreate(nil,27,27,8,0,
                            colorSpace,kCGImageAlphaPremultipliedLast);
   CFRelease(colorSpace);
   return context;
}

- (CGImageRef)createBackArrowImageRef
{
   CGContextRef context = [self createContext];
	
   // set the fill color
   CGColorRef fillColor = [[UIColor blackColor] CGColor];
   CGContextSetFillColor(context, CGColorGetComponents(fillColor));
	
   CGContextBeginPath(context);
   CGContextMoveToPoint(context, 8.0f, 13.0f);	
   CGContextAddLineToPoint(context, 24.0f, 4.0f);
   CGContextAddLineToPoint(context, 24.0f, 22.0f);
   CGContextClosePath(context);
   CGContextFillPath(context);
	
   // convert the context into a CGImageRef
   CGImageRef image = CGBitmapContextCreateImage(context);
   CGContextRelease(context);
	
   return image;
}

- (UIBarButtonItem *)backButton
{
   CGImageRef theCGImage = [self createBackArrowImageRef];
   UIImage *backImage = [[UIImage alloc] initWithCGImage:theCGImage];
   CGImageRelease(theCGImage);
	
   UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:backImage
                                        style:UIBarButtonItemStylePlain 
                                        target:self.webView 
                                        action:@selector(goBack)];
   
   [backImage release], backImage = nil;
	
   return [backButton autorelease];
}

See you at WWDC 2008

Every year around this time a mass migration occurs around the world. Large numbers of Mac developers make the long arduous journey to San Francisco to gather, learn, network, and socialize.

This year I make my own way to join this strange ritual for the first time.

It’s time for Apple’s World Wide Developers Conference (WWDC). A solid week of full emersion in all things Mac and iPhone.

I’m looking forward to finally meeting many people I’ve previously only known through following their Twitter feeds, reading their blogs, using their software, or chatting with them in IRC. It’s a strange business we’re in where most of our contacts are strictly via electronic means.

With MacBook Pro, iPhone, and code in hand; I’m off.

Resolution Independent Buttons

Sean Patrick O’Brien shares his approach and sample code for creating attractive resolution independent controls in Cocoa.

I, like most developers, love shiny new user interfaces. Rounded corners, gradients, drop shadows, custom drawing — all of these things make me smile.

Sean takes us through his steps for prototyping his controls in Photoshop to get the look just right. Then he walks us through his code step by step. Complete sample Xcode project included.

Core Animation Podcast

In my previous post, Mac and iPhone Programming Books, I briefly mentioned the eBook Core Animation for OS X.

Today, the publisher, The Pragmatic Programmers announced a new podcast interview with the book’s author, Bill Dudney.

The podcast is obviously pushing his new book. But, if you have any interest in Core Animation or iPhone development it does have some interesting information and it’s worth listening too.

UPDATE: The Mac Developer Network is also featuring Bill Dudney in their latest Late Night Cocoa Podcast episode, Introduction to Core Animation.

Mac and iPhone Programming Books

The introduction of Apple’s iPhone Software Development Kit has lead several friends to ask me for book recommendations to help them get started developing for the iPhone and Mac.

While the selection is not huge at the moment, the few books that do exist are actually quite good.

There are two primary technologies used to develop iphone and Mac software. Objective-C is the programming language and Cocoa is the framework that provides the building blocks for building applications.

Cocoa Programming for Mac OS X (3rd Edition), by Aaron Hilegass, is probably the most recommended Mac programming book published. The current edition is outdated, but serves as a very good teaching aid for the beginning Cocoa programmer. But, if you can wait until this summer, the 3rd edition of this book will cover the additions and improvements to the Cocoa framework that Apple has added in Tiger and Leopard.

Cocoa uses the Objective-C language and
Programming in Objective-C, by Stephen Kochan, teaches the fundamentals you’ll need to get your work done.

Alternatively, you may want to look into the eBook Learn Objective-C on the Macintosh, By Mark Dalrymple and Scott Knaster. I haven’t read this one, but have heard good things.

One of the cool things about Objective-C is that it’s basically an extension of the C programming language. While programming in straight C is not usually required, it does come up from time to time and it can be very helpful to know what you are doing. If you don’t know C, you many want to check out the eBook Learn C on the Macintosh, By Dave Mark.

The books listed above will get you started programming for the Mac and iPhone, but if you are interested in advanced topics or event Apple Script, the following books might be helpful.

I’ve read most of these books, but the few that I haven’t were recommended to me and have very good reputations.

The Mac Developer Network

From the creator of the Late Night Cocoa podcast comes The Mac Developer Netowrk (MacDevNet.com) and the new Mac Developer Roundtable podcast.

The Mac Developer Network (MDN) is hoping to become your first port of call for all things to do with Mac Development.

Scotty has done a wonderful job with Late Night Cocoa over the past year and that makes me think the Mac Dev Net is going to be a great resource as its content and podcast episodes build up.

With the recent increase in Mac users and developers, it’s surprising there aren’t more programming resources outside of The Apple Developer Connection. It’s a great community booster to have Cocoa developer resources like Mac Dev Net, CocoaDev.com, and Cocoa Dev Central.

Bullfrog Game Design: Dynamic Bugs

Developing software is an interesting process. There are times where I work very hard with little to show for it for several days. Then there are those days where I can knock out a ton of tasks on my “To Do” list with little effort. Usually, one state directly follows the other.

I recently spent several days working on the mechanism that Bullfrog 2 will use to load level and bug definitions. There was much reworking and testing involved. Now that the work is complete, designing new levels and bugs should take little time and effort.

Hardcoded Bugs

In the original Bullfrog, the player was tasked with munching bugs as fast as possible. Bugs were randomly spawned on the screen based on a simple algorithm. This algorithm would generate a certain number of bugs depending on what round the player had reached. For example the gnat was generated using the following calculation.

int numberOfGnats = roundIndex * GNAT_SPAWN_RATE;
listing 1

Each bug type had it’s own spawn formula and custom class. Each bug class would then be allocated and tracked in a NSMutableArray during the round.

NSPoint origin = GetRandomGamePoint(gameRect);
unsigned int direction = GetRandomAngle();
switch([bugDef bugType])
{
   case GnatType:
      bug = [[Gnat alloc] initAtPosition:origin
                           withDirection:direction];
      break;					
//   ...
}
listing 2

This approach worked fairly well for a simple game using random spawn points on a simple game board. There were no level design elements to worry about. A bug was either alive and on the screen, or it had been eaten.

Dynamic Bugs

For Bullfrog 2, we really wanted to move away from randomly generated rounds and bugs to designed levels. We plan to have multiple levels with unique artwork and challenges. But how do we define bugs and have them spawn based on a definition file?

We could read in the definition and run through a big switch statement with a case block for each bug type similar to the code above (listing 2) used in the first Bullfrog. But, this gets nasty pretty quick.

We’re also adding new game elements to Bullfrog 2. Players will have obstacles such as rocks and water to deal with while hunting down bugs. These elements also need to be defined and tracked inside the game.

With a bit of imagination, rocks and bugs are basically the same thing except for a few different attributes. Bugs can move, rocks can’t. A mosquito can damage the player, but a rock can block the player’s movement.

This lead us to a base class we’re calling Actor. Each actor can be completely defined with a set of attributes which denote size, animation, and other things.

We still have the problem of needing unique AI (artificial intelligence) for the different bugs. Using just the Actor class won’t provide us with customized code to define personality attributes such as chase and escape behaviors.

So we defined a set of Actor subclasses that provide the custom behaviors of the various bugs and other objects populating the Bullfrog world. But, with each new game object, our switch case grows in complexity.

Objective-C to the Rescue

This is where our decision to use Objective-C pays off. By using the dynamic nature of the Objective-C we can allocate and initialize our actors at runtime without using a huge switch statement.

Given the following Actor definitions (listing 3) we can dynamically generate the level’s actors with a simple loop (listing 4).


   
      class
      BFRock
      blocksMovement
      1
   
   
      class
      BFGnat
      blocksMovement
      0
      moveSpeed
      0.005
      turnFrequency
      5
      turnSpeed
      20
   

listing 3
- (void)loadActorsDefinition:(NSArray *)actorsDefinition 
                   intoLayer:(NSMutableArray *)layer
{
   id actor;
   NSDictionary *actorDef;
   for(actorDef in actorsDefinition) {
      NSString *actorClass = [actorDef valueForKey:@"class"];
      actor = [[NSClassFromString(actorClass) alloc] init];
      if (![actor isKindOfClass:[OLActor class]]) continue;
      [actor loadDefinition:actorDef];
      [layer addObject:actor];
   }
}
listing 4

The key piece here is the function: NSClassFromString(NSString *str). This Foundation function returns a Class object that can then be used just like your hardcoded class definition for allocating a new instance.

In the above function (listing 4) we get the “class” attribute from the XML and feed that into the NSClassFromString function to get our Class. Then pass in the XML for this particular Actor into the instance method -loadDefinition: on the Actor class. Some more Objective-C runtime magic reads in the defined attributes and stores them in the Actor instance properties using key-value coding (listing 5).

NSString *key;
for (key in [definition allKeys]) {
   [self setValue:[definition valueForKey:key] forKey:key];
}
listing 5

Now all actors for each defined level are easily loaded and we don’t have to constantly rewrite or modify our code each time we add a new type of bug or game object.

The difference in complexity and number of lines of code in Bullfrog 2 is greatly reduced because of the magic that Objective-C provides. Dynamic class loading is very powerful and provides us with great flexibility moving forward.