A git workflow for the app store submission process

When you submit an app to the app store for review, what do you do?

Do you simply stop development on the app until the review comes back? Do you keep working on new features? If your app is denied, do you try to resubmit it with the new features you added since the first submission? Do you try to undo everything you did, fix the issues found in the review, and resubmit? Do you switch over to another app?

The app store review process causes some interesting workflow challenges, but git makes them easy to deal with.

Let’s assume that you’re already using Git and Dropbox (or some other DVCS such as mercurial, and some other form of backup or a networked repository). If you aren’t, you should be, so stop reading this article and go read this one instead.

Let’s also assume that you are familiar with basic DVCS concepts such as branching, merging, and tagging. If you aren’t, the git book is a great place to learn.

So, we are ready to start working on some cool new features. We’ll start by creating a branch for our next version – in this case, version 1.3.

Martys-Mac:WhichEpisode marty$ git checkout -b 1.3
M	Which Episode.xcodeproj/project.xcworkspace/xcuserdata/marty.xcuserdatad/UserInterfaceState.xcuserstate
Switched to a new branch '1.3'

Now we’re ready to make our changes. We’ll fix a few bugs, add some features, tweak some views, and so on. This might take a few commits – that’s totally fine.

...make changes...
git commit -am ...

...make changes...
git commit -am ...

...make changes...
git commit -am ...

Ok, we’re now done version 1.3, and we’ve uploaded the binary to the app store for review. Time to end our work on the 1.3 branch by merging it back in to master, and then pushing our changes to our repo in DropBox. You can also push to your remote repo for safekeeping at any point during development of 1.3, of course.

Martys-Mac:WhichEpisode marty$ git checkout master
Switched to branch 'master'
Martys-Mac:WhichEpisode marty$ git merge 1.3
Updating 41988bd..90adff4
Fast-forward
 Default-Portrait@2x~ipad.png                       | Bin 0 -> 18121 bytes
 Default-Portrait~ipad.png                          | Bin 0 -> 5949 bytes

Martys-Mac:WhichEpisode marty$ git push
Total 0 (delta 0), reused 0 (delta 0)
To /Users/marty/Dropbox/Projects/WhichEpisode.git/
   41988bd..90adff4  master -> master

At this point, the branch for 1.3 is still there, but we won’t need to touch it again unless something goes wrong with our submission. However, we are ready to work on our next release, 1.4, so let’s create another branch for it:

Martys-Mac:WhichEpisode marty$ git checkout -b 1.4
Switched to a new branch '1.4'

You can now start working on all the cool new features for your next release.
If 1.3 gets rejected, and you need to apply a fix to it, just switch to the 1.3 branch, make the change, and commit it.

Martys-Mac:WhichEpisode marty$ git checkout 1.3
Switched to branch '1.3'

...fix bug...
git commit -am ....

Re-submit the binary, then switch back to the 1.4 branch and merge in the change, to make sure it stays up to date with any important fixes.

Martys-Mac:WhichEpisode marty$ git checkout 1.4
Switched to branch '1.4'
Martys-Mac:WhichEpisode marty$ git merge 1.3
Updating 90adff4..3152f6d
Fast-forward
 0 files changed
 create mode 100644 test.txt

Astute readers may notice that at this point, we have a change in the 1.3 branch that’s not in master. I can live with that, because I know the change will find its way to master once the 1.4 branch is merged, but if you are really worried you can always merge 1.3 to master again.

Martys-Mac:WhichEpisode marty$ git checkout master
Switched to branch 'master'
Martys-Mac:WhichEpisode marty$ git merge 1.3
Updating 90adff4..3152f6d
Fast-forward
 0 files changed
 create mode 100644 test.txt

So, that’s pretty much how I use git to work with the app store release process. It lets me submit releases to the app store for review, and then continue development in another branch, without worrying about what to do if my app gets rejected.

This has been working quite well for me, but I am curious as to what everyone else does. Thoughts? Ideas? Ways to improve the process? Do something completely different? Use git-flow? I would love to hear your stories!

Make your UITableViews stand out with alternating row colors

UITableViews are the foundation of many iOS apps. Although they are pretty powerful and flexible, they are also very bland in their default configuration.

A quick and easy way to add some style to your boring UITableViews is to add alternating row colors. This gives them some visual ‘pop’ and improves readibility. No fancy design skills required!

Here is a sample UITableView from 20 Rep Squats. It’s a little bit… monotonous.

iOS Simulator Screen shot 2013-01-12 6.51.28 PM

Let’s spice it up a bit. Open your UITableViewController’s .m file, and insert the following code:

-(void) tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath
{
    UIColor* color = indexPath.row % 2 == 0 ? [UIColor whiteColor] : [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
    cell.backgroundColor = color;
}

All we are doing is specifying that even numbered rows will have a white background, and odd numbered rows will have a nice subtle light grey background. Of course, you’ll want to store your background colors in fields or constants, and not have to regenerate them with colorWithRed:geen:blue: every time, but that’s beside the point of this post.

The result looks like this:

iOS Simulator Screen shot 2013-01-12 6.51.01 PM

And there you have it – with only a few seconds of effort, you can take your UITableViews from blah to beautiful! Or blah to average, at the very least.

iOS App Postmortems: Bug Tracker

Bug Tracker is now available on the app store.

Overview:

As the name implies, Bug Tracker is a bug and issue tracking tool targeted at software developers. It is a standalone application, requiring no external server software. The app store is full of iOS clients for tools like Bugzilla, Jira, mantis, and FogBugz, but contains virtually no iOS-only issue trackers.

Development Time:

Around 44 hours or so, plus a chunk of time spent working on ios-queryable.

Review Time (time spent in the iOS app submission queue):

6 days. Thanks for the relatively speedy review, Apple! I think that was my fastest one so far.

New technologies I learned and used:

Aside from a heavy dose of Core Data, there wasn’t really anything particularly new here.

What went right:

  • With Bug Tracker, I took a data-first approach – creating virtually the entire Core Data model before writing a line of code. I think that this helped narrow down the focus of the app and get straight to the point of what it really needed to do. Sometimes I find that starting with a UI (my usual approach) can lead down a never-ending road of ‘hey, I could add this feature here…’. Starting with the data and building the UI on top of it seemed work quite nicely.
  • Normally, after developing an app primarily using the simulator, and the switching over to my iPod for testing, I find a number of issues or things that don’t quite work right. With Bug Tracker, everything was surprisingly usable from the start on the device, and I didn’t have to go back and rethink designs or change the UI.

What went wrong:

  • Well, the fact that Core Data annoyed me so much that I had to write a library to make it suck less can’t be a good sign. But it did turn out to be a fairly useful tool.
  • In terms of design – always a challenge – I found myself struggling with the limitations of UITabBarControllers.and UINavigationControllers. Although these form the backbone of navigation in most of my apps, I am starting to have second thoughts about their usability and the patterns of interaction that they demand.
  • Finally, although the title of this blog is ‘App Per Month’, Bug Tracker’s development put a bit of a stop to the idea of monthly releases. For various reasons, including starting a challenging new job, I simply haven’t had as much time as I would’ve liked for iOS development. The result is that Bug Tracker’s 44 hours or so of development was spread out over a period of nearly 3 months.

Future plans:

The ‘stuff I want to do’ list is pretty long here, but a lot of it depends on what users want. I think iCloud support would be quite nice, for both backup purposes and cross-device usage. Saving of searches would be a great way to enhance the dashboard and the search capabilities. Icons for things like issue types and priorities, and UI enhancements in general, would also be nice. Oh, and a proper iPad version would be handy, too.

But really, it all depends on you, so if there’s something you would like to see in Bug Tracker, let me know!

Are single-page sites an effective marketing tool for iPhone apps?

I’m not sure, but I’d like to find out! A few cursory Google searches didn’t come up with much in the way of answers.

As part of my quest to increase app revenue and marketing efforts, I have created a new home for Bug Tracker. It now lives at http://bugtrackerapp.com, thanks to a handy WordPress Template from Apptamin. I will probably tweak the design and the content in the future, but for now, it’s good enough.

I would like to find out if this type of marketing can result in improved sales numbers. Given that domains are reasonably cheap, and hosting additional ones with my current hosting provider doesn’t cost anything, it seems like a relatively risk-free idea. It also gives me some more practice with SEO – something I seriously need to need to improve on.

Unfortunately, there’s no way to know for sure whether a sale came from the website or from some other method (searching in iTunes, etc.), but at the very least I can keep track of clicks on the ‘Available in the App Store’ button.

In addition to Bug Tracker, I will probably put up another website or two for some of my older apps, such as 20 Rep Squats and Which Episode, to see if I can get a before/after split on sales numbers.

What else are you guys doing to market your apps?

Announcing: Bug Tracker for iOS!

I am happy to announce that my latest app, Bug Tracker, is now available on the app store!

bug-tracker

Bug Tracker is exactly what it sounds like – a standalone bug tracker for your iOS device. Although it took a bit longer to finish than I had hoped, it was a great learning experience that resulted in a nifty little app as well as an open-source library for making Core Data queries more LINQ-like.

A postmortem will be coming soon!

2012 In Review: A Year Of iOS Apps And Blogging

Now that it’s 2013, I thought it would be a good time to look back at the past year. It was my first year of blogging and iOS app development, and it was full of successes, failures, and surprises.

The Goals

A year ago, I came up with a number of goals I wanted to achieve for the year. Time to see how I did!

  • Sign up for the iOS Developer Program
    Success!
  • Release my first app to the app store by the end of January
    Success! Well, technically I was slightly late, but close enough!
  • Release some open-source Objective-C code
    Success! I have released the virtually unnoticed ReallyRandom class for grabbing truly random numbers from http://random.org, and the reasonably popular ios-queryable, which makes writing Core Data queries far easier.
  • Start answering Objective-C or iOS questions on Stack Overflow
    Success – although I would’ve liked to have answered a few more.
  • Blog at least twice per week
    Failed. It looks like I am averaging about 1 post per week.
  • Come up with 10 legitimate ideas for App Store apps
    Failed. I am currently at 9 ideas.
  • Implement and release one of those 10 ideas every month or so
    Failed. I currently have 8 apps in the app store, with another one inches away from being submitted for review.

The Apps

As mentioned above, I currently have 8 apps in the App Store, and another one almost out the door.

My most successful apps have been Which Episode? and 20 Rep Squats. Which Episode? has sold the highest number of copies, and 20 Rep Squats has generated the most revenue (despite being a niche app for an incredibly small niche) thanks to it’s $2.99 price tag.

My least successful or most disappointing app has been Photo Todo. Despite being what I think is a nifty take on the typical todo list app, it has sold an amazingly low number of copies.

I think that my biggest weaknesses on the app side of things are a lack of marketing and a lack of UI design skills. Combined, these two things make it harder for my apps to stand out from the crowd.

The Website

Traffic has been steadily increasing every month (aside from a minor hiccup at Christmas), and I am now averaging roughly 250 visits per day. All website-related metrics are trending upwards, as this chart shows.

2012-stats

Looking Ahead…

Here are my goals for 2013.

  • Release at least 8 more apps
  • Double my average monthly website traffic
  • Double my average monthly app revenue
  • Step up my marketing efforts to increase sales of existing apps
  • Try to blog a bit more often
  • Keep better stats on downloads and sales (since the Apple-provided tools are woefully inept, and using third party app analytics services violates Apple’s developer agreement)

So, how did you do in 2012? What are your goals for next year?