Overcoming the iPhone Development Gumption Trap
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 - Comments - Tags: iPhone,Development
Karate Index
Karate Index is a fast, cross referenced glossary of Karate Terms:
A lite version is available free, with a loading delay to access glossary definitions.
- Index information is stored on your phone. Fast access and no network connectivity required.
- Each page has been cross referenced for fast browsing of glossary terms.
- Random flashcard functionality allows you to test your knowledge of Karate terms.
Karate Index uses some of the information available on the Wikipedia Karate page. This data has been modified, optimized and cross referenced for the iPhone and is available under the CCA - ShareAlike 3.0 Unported License.
Permalink - Comments - Tags: Development,Karate Index,iPhone,App,Glossaries
SomethingOrOtherSoft
Igor Zevaka, a colleague of mine recently started a blog at SomethingOrOtherSoft.com. He is a smart guy and can definitely bring the funny.
The attached photo is my desk after much beak snapping, flapping of great dirty wings and scrabbling claws. Rawwwrrrk FTW!
Permalink - Comments - Tags: Links
Ettin
The other crews in C company made jokes about Lieutenant Jordan's tank, it was lucky they said, or haunted, depending on who you asked. The boys in Jordan's crew knew better, they didn't talk about it, but they had all had glimpses of the thing that kept them safe. A flash of brilliant blue scales twisting behind the ammo store. A blinking green eye deep in the breach when they cleaned the barrel. Something lived in the battered old Sherman, something that hid in the dark places and came out to play when bullets ricocheted and shells roared. The old man knew what it was and Teddy the loader said he heard him talking to it sometimes. They sure as hell never asked him about it.
Lieutenant William Jordan had commanded C company since Sicily, and before that, had fought in Tunisia. He had been one of the few to come out of that goddamn mess at Kasserine unscathed. Nobody in the regiment, and probably nobody in the whole 3rd army, knew more about tanks and the bloody business of fighting in them. He was a detached man, not blustering like some of the officers in the CCA, but not kindly either. Some of the men said he had a thousand yard stare, like he had seen too much and lost his marbles. Anyone in first platoon would throw down with a man for talking about the Lieutenant like that. He might not be much of a conversationalist, but if the tank wasn't lucky, then he sure as hell was.
Tonight the Lieutenant was sitting on the warm engine cover of his Sherman, reading a dog-eared romance book by the light of a kerosene lamp and occasionally taking a swig from a blackened hip flask. There was a dusting of snow on the ground and the tank tracks left an icy brown furrow into the field where it was sitting.
The boys had been given an evening pass and were in the village. He had finished the report the captain had been harrying him for and, until the other officers got back from regiment, had an hour or two to take his leisure.
He saw the blue flash of movement at his elbow, but chose to ignore it. He didn't feel like playing the creature's games tonight, he was tired and felt a surge of jealous indignation that this brief period of relaxation would be so interrupted. The creature insisted, as he knew it would, as it always did. He didn't hear a voice and barely saw the creature itself, but it always managed convey it's meaning directly to the core of Jordan's consciousness. Something was happening over the eastern horizon, something was coming.
Everything that had happened in the last few months told Jordan that the creature was wrong this time. The Germans had kept up a dogged, tenacious and bloody defence since the Normandy landings, but they had suffered so many reversals and had been constantly pushed back all along the line from the channel coast to Switzerland. They had even bigger problems in the east, the Russians now taking full and horrific revenge for the atrocities of Barbarossa. Surely the last German offensives were behind them. This must be a feint, a local counter-attack to shore up their lines, it couldn't be a major offensive.
Jordan sighed, he hoped the boys had found what they were looking for in the village tonight, because they wouldn't get another chance for R&R for who knows how long. How the hell was he going to explain this to the captain. The company, the division, probably the whole damn third army would have to move quickly for this thing, if what the creature had murmured was right, and Jordan knew it was. It always was.
Mercifully, he was spared the frustration of trying to explain to the captain that he had a "hunch" that a massive armored spearhead was about to punch through the Ardennes forest right between the American and British lines. Captain Forester met him on the road, flying back from regiment with news of the attack already in hand.
"Will ! Get the boys back in formation and fueling those tanks. Looks like the Krauts have got some fight left after all. Report to the company CP when things are moving and I'll tell you the rest."
With that, he slammed his hand into the door of the jeep and careened down the road, tires sending up plumes of muddy ice. Peering after him for a moment, Jordan shook his head, stomped on the gas of his own jeep, speeding off in the opposite direction. He would pick up his boys first, he might need their help persuading some of the other C company men that leave was canceled.
I would like to finish this story some day ...
Permalink - Comments - Tags: Stories,World War Two
Ballet Index
Ballet Index is a fast, cross referenced glossary of Ballet Terms:
A lite version is available free, with a loading delay to access glossary definitions.
- Index information is stored on your phone. Fast access and no network connectivity required.
- Each page has been cross referenced for fast browsing of glossary terms.
- Random flashcard functionality allows you to test your knowledge of Ballet terms (In version 1.1).
Ballet Index uses some of the information available on the Wikipedia Ballet page. This data has been modified, optimized and cross referenced for the iPhone.
Permalink - Comments - Tags: Development,Ballet Index,iPhone,App,Glossaries
[First Page] [Prev] Showing page 4 of 14 pages [Next] [Last Page]