Overcoming the iPhone Development Gumption Trap

September 11, 2009, 8:00 am

I finished, and submitted to the App Store, my first iPhone application. Despite the technical simplicity of the application, I do feel a sense of satisfaction that I overcame a thornier problem, The Gumption Trap. For me, the programming equivalent of writers block.

In this case it was Objective-C and to a lesser extent the iPhone development Framework. I have been enjoying my new iPhone for the last month or so and have had access to the iPhone SDK on my Macbook for much longer than that. But, I hadn't got much further than perusing the Objective-C Primer.

I think the biggest problem, for me, was finding a specific problem to solve. Eventually I came up with something simple enough to avoid getting bogged down and with just enough complexity to warrant an App Store submission. A fast, hyperlinked glossary of Ballet terms and their definitions. I Spent about a week from conception to submission and I encountered some interesting problems as I broke into iPhone development.

Objective-C

Ok, there isn't too much to say here. For a developer (even a reasonably experienced developer) who hasn't encounted it before, it's a bit weird. As Matt Gemmell says in his excellent iPhone Development Emergency Guide post:

Objective-C synbtax looks weird, but it's only visually different ... It's Verbose, but it's more explanatory. Accept it and move on.

That was pretty accurate in retrospect. The strangeness certainly added to the entry price, but once I was through the door, it quickly began to make sense.

Artwork

With no budget to spend on a real designer, I was forced to rely on my own dubious artistic talents to come up with my Icon art for the the three Glossary apps I have built:

Project Configuration

When I showed a collegue the intial screens for the Ballet Glossary, he suggested that his boys might like one for Karate terms. It made sense to share the code between the two apps, so this was a good reason to go through all the various bits and pieces that make up an XCode project:

  • The xcodeproj is actually a directory containing two PBX files (heirachical project definition files) and a project pList file. Two for project configuration stuff and a PBX containing user specific stuff (layouts, breakpoints etc..).
  • The application pList file included in the package. You can store useful project configuration stuff here like the version, app name etc. I ended up having one of these for each of the targets I set up for the project (lite and paid).
  • 512px and 57px versions of the application icon as PNG files. The 57px version is refered to in the project pList file to set the icon for the project (CFBundleIconFile).
  • Any xib files you are using in your app. Basically freeze dried UI objects.
  • Your Objective-C source files.

Pink!

Writing a Ballet app, I figured pink might be a good color scheme to go with. I love a good steriotype. I thought this would probably be trivial. It was pretty simple, but not entirely obvious at the time.

The first thing I did was set the barStyle on the UINavigationBar to UIBarStyleBlack, then modified the tintColor to be pink. This worked fine for the Navigation Bar section of the UI. Pretty obvious so far, but I still needed to make the UITableView pink.

At the time, setting the backgroundColor property on the UITableView didn't update the background colors for the heirachy of views in the table, so I ended up with the UILabels in the table using the original white background.

Setting the opaque property (to NO) on the UITableViewCell.textLabel (UILabel) object failed because it was being overwritten sometime after the cellForRowAtIndexPath message had been called. So I ended up insantiating my own UILabel, setting it's opaque property and then adding it as a subview of the UITableViewCell.contentView.

UILabel * label = [[[UILabel alloc] init] autorelease]; label.frame = CGRectMake(40.0f, 10.0f, 220.0f, 22.0f); label.textColor = [UIColor blackColor]; label.opaque = NO; label.tag = 1; [cell.contentView addSubview:label];

I set the tag on the UILabel so I could subsequently find it to set the text property as the cells are updated. While I was writing up this post I discovered that the backgroundColor property on the UITableView has been fixed to update it's child views and was able to remove this unnessasary complexity.

Intercepting Hyperlinks in a UIWebView

I wanted to support hyperlinked definitions for my Glossary terms so a user could jump around between definitions to get a more complete understanding of the text. My origional definition view was a UITableView and it seemed like adding the hyperlinks to the text (in that view) wasn't going to be easy. It made sense to use the UIWebView instead, after all, that is the UI paradigm that I was going for.

So I create a UI web view and populate it with some HTML, style it with CSS and implement the UIWebViewDelegate to capture the HTTP requests coming from the page. The following shouldStartLoadWithRequest message is called when the user touches an anchor tag in the page, if you return YES, then the HREF for the tag is used to make an HTTP request, if you return NO, then the click is ignored (with alternate handling): - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if (navigationType == UIWebViewNavigationTypeLinkClicked) { // strip off the href prefix ("glos://" or "http://") NSString * key = [request.URL.absoluteString substringFromIndex:7]; currentTerm = [self.dataController objectInListWithEscapedTerm:key]; if (!currentTerm) return NO; // don't really want to do anything // push the term on the stack (for a simple page history navigation) [self pushTerm:currentTerm.term]; // set the html with the description for the term we looked up [self.webView loadHTMLString:[self formatData] baseURL:nil]; return NO; } return YES; }

CSS was the perfect mechanism to customize the look of the page and because the UIWebView is a Safari browser I was able to use the -webkit-border stuff to get rounded corners on my page elements. This is something that I have wanted use in other web projects, but a desire to support the lesser browsers have prevented me:

ul { margin: 5px 30px 5px 30px; background-color: #e9f0f4; -webkit-border-bottom-left-radius: 30px 30px; -webkit-border-bottom-right-radius: 30px 30px; -webkit-border-top-left-radius: 30px 30px; -webkit-border-top-right-radius: 30px 30px; }

A Lite Version

Based on Nick Maher's experience with TripView and comments on the Mobile Orchard Podcast, it seems that the inclusion of a free, yet somehow limited version of your paid app is a good idea. I didn't imagine my Glossary apps selling many copies, but I thought I would be a good exercise to build a Lite version anyway. I decided that the value that my application adds, that perhaps warrants the 99c purchase price, is that the data is accessible quickly. So the lite version needed to demonstrate this value, but also limit access to it. I had a couple of solutions and eventually went with the second:

  • Fast access to a limited number of terms and then, once that quota is used up, a link to Wikipedia.
  • Fast access to the first definition lookup and then a loading delay for every subsequent term (with no limit on the number of terms accessible offline).

What Next?

So there was a surprising amount of stuff to think about for such a simple application, but I think I learnt quite a lot and have a good stepping stone for my next project.

Permalink - Tags: iPhone,Development