Behind The App: Twitterrific 5

I’ve always loved shows that take you behind the scenes of creative efforts: Project Runway and Classic Albums being two of my favorites. Here’s one about the development of Twitterrific 5.

Since a lot of the people reading this aren’t developers, I’m going to keep the jargon to a minimum. You’ll be able to enjoy this piece even if you don’t know what an Xcode is.

Statistics

To get an idea of the scope of the project, and see who worked on it, let’s look at a few numbers.

The first source code file was created on February 15th, 2012. Since that first check-in, there have been 2032 changes resulting in 824 files. Of those files, 73% are source code, 25% are images, and 2% are other assets such as fonts and sounds.

Sean Heber was responsible for 976 changes, while I came in second with roughly half as many (557). Tyler Anderson made 397 commits and David Lanham followed that with 95. Anthony Piraino and Gedeon Maheux picked up the rest.

We did weekly beta releases between October 26th and November 19th. The following day, we submitted the build to Apple for approval, which happened one week later. The app was released today, which is actually yesterday in Japan. :-)

Twitter Changes

If you’re at all interested in Twitter’s development ecosystem, you know that approximately six months into our product development there were some major changes announced.

In August, a posting on Twitter’s developer blog announced that changes were coming. In spite of the new requirements and limitations, we were happy to know that our API access wasn’t going to be revoked. Since the early days of the project, we had been worried that third-party development might be eliminated completely.

As more details about API 1.1 became available in September, we became even more upbeat about the changes. There were a lot of improvements in the API and the new infrastructure was extremely robust. Adapting our existing code to the new API took very little time and allowed us to simplify a lot of our internal code. It’s good to know that management’s decision to control the core Twitter experience hasn’t affected their great API engineering.

At this point in time, we also learned that we had plenty of user tokens for the upcoming version. We agreed with our friends at Tapbots, there is no reason to panic.

One downside to the limit of user tokens is that we can’t afford the “cost” of a free app. If someone downloads a free version of Twitterrific and then uses it once, we can never reclaim that token. Tokens are a scarce resource that developers have to manage carefully in order to recoup their development costs. If you’re holding out for a price drop with our app, you’ll be disappointed. The price of Twitter apps is going to rise from now on.

Development Approach

So when you have five people working on a piece of software, how do you go about it?

This time around, we took a much more design-centric approach. When you have a large project, be it a movie or a piece of software, you have to have someone calling the creative shots. For Twitterrific 5, that person was David Lanham.

We’d done Twitter clients before and honestly weren’t that enthused about doing another one. That was until we saw a complete and clickable prototype that David had created. That “wow!” moment you have when you launch and start to use Twitterrific 5 is something we experienced last February. We all knew we had to make this real, even if it was a bit crazy. Our foreman, Gedeon Maheux, made the call and the project began.

Some natural pairings occurred between the three developers and single designer.

As senior developers, Sean Heber and I decided to split the workload between the front-end and the back-end. Sean had a part in everything you see on screen. I had a part in everything you see going over port 443 (for you non-developers who won’t get that joke, that’s the secure network connection that the Twitter API uses.)

This turned out to be a great decision. The user interface doesn’t depend on knowledge of how data is transported over the network, processed and then cached in a database. In fact, in the early stages of the project, much of our back-end existed as a separate project with no user interface. It used automated tests that exercised multi-threaded access to the Twitter API. This independence between the UI and the network services allows new APIs to be added quickly and easily.

(AND IT MAKES ME KING OF THE BACK END IF YOU KNOW WHAT I MEAN)

One of the benefits of writing your own version of UIKit is that you have a pretty complete understanding on how to use it effectively. All the sexy animations and views you see in the the app are Sean’s doing. As he continued to amaze us all, we came up for a word for what he does: juice. For example, just the other day, he closed an issue titled “Add JUICE™ to Photo view”. (You’ll see that change in the 5.0.1 release that’s in review now, and yeah, it’s great.)

Splitting the front and back-end work between Sean and myself had another benefit: we were constantly optimizing our code so that it would make the other guy’s code work better. A lot of people have commented on how fast Twitterrific feels: hundreds of iterations made that happen.

Another pairing was between David Lanham and Tyler Anderson. From the start, we knew that we wanted customers to have control over the appearance of their timelines. Since Sean had done of version of UIAppearance proxy in Chameleon, that was a natural choice to accomplish our goals.

What happened next though, surprised us in a very good way. David started using Xcode.

Since Tyler was writing code that allowed all the appearance modifications to be collected in a single file, it was easy for David to go into that file and tweak the settings to get things exactly as he wanted. Any coder who’s worked closely with a designer had heard these phrases: “Can you replace this image?” “Tweak this color please!” “Nudge that button to the right a few pixels.”

Instead, David was adding files to Xcode and modifying UIColor and UIEdgeInset definitions by himself. Letting the designer take control of his designs, do test builds, and refine the interface produced some amazing results. And it let our developers focus on what they do best: typing code.

As work progressed on the product, we realized we were making something special. When that happens, all sorts of crazy and wonderful things start to form without you really knowing how or why. The best example is when Sean and David added gestures. Twitterrific was already in beta at that point and we were completely happy with the action menus, but the two of them went quiet for a couple of days saying only they were working on “something cool”. And they were right: we can’t imagine using the app without gestures now.

A Clean Slate

So now that you’ve heard about what led up to today’s release, let’s finish with some thoughts about future directions.

As soon as you launch Twitterrific 5, you’ll realize that it’s a clean slate. The visual design is obviously a fresh start, but everything under the covers is as well. When presented with a clean slate, you’re very careful what goes on it. It’s best feature is simplicity. I wrote about Gruber’s First Law of iPhone Development four years ago:

Figure out the absolute least you need to do to implement the idea, do just that, and then polish the hell out of the experience.

That still holds true, and we feel like we’ve done the least and polished the most.

We are well aware that people are going to complain about missing features: push notifications and streaming are obvious examples. But so are trends, and video support, and in-line photos, and… well none of that matters. We believe in building opinionated software.

The product you have in your hands is what we wanted and needed it to be. As the tagline on the website says, “A simply beautiful way to tweet.” We achieved that goal.

Personally, I find myself actively disabling notifications in most of the apps I install these days. Notifications are great when used in moderation, but it’s very easy to use them to the point of distraction. Since I read Twitter as free time permits, I don’t need a reminder. Similarly, a constant flow of streaming tweets interrupting my day sounds more like a bug than a feature.

But guess what? That doesn’t matter either. I’m just one of the opinions that made this software.

And now we’re going to start listening to our customer’s opinions. We’re all excited to get feedback from a larger audience and see how that fits in with our new minimalist vision. If you think Twitterrific is good now, just wait until you see what happens with your collaboration.

Don’t design for early adopters

If you’re like me, the iPad has changed how you look at computers in just a matter of weeks. The possibilities for this device seem endless. It’s natural at this point to start thinking about the future, and to do that thinking in terms of the past.

As an example, we’ve been getting plenty of feature requests for Twitterrific that ask for features and capabilities that exist in other mobile and desktop software. That’s not surprising, since one of our early decisions with the iPad app was to trim the app down to its bare essentials.

Part of this had to do with schedule constraints. Sixty days was not a lot of time to build a product from scratch.

But a more important reason for paring back the design was to simplify the user interface. A new kind of user is about to be introduced to a computer that they can actually use: less interface is more as far as they’re concerned. We designed our iPad app with our families in mind, not the Twitter power user.

It turns out that our design intuition was pretty good:

The non-tech-savvy users want something simple, to push an icon and get your e-mail and go online. With the iPad, people don’t feel intimidated by it.

Mary Elizabeth O’Conner

To this technical-ninny it’s clear
In my compromised 100th year,
    That to read and to write
    Are again within sight

Of this Apple iPad pioneer.

Virginia

Even folks that have access to the latest and greatest technology are preferring the iPad over more complex devices. Initial statistics also show that the iPad has an older demographic.

Of course, 300,000 geeks like you and me don’t fall into that category. We’re the first ones standing in line at the Apple store, and the first ones to use all this cool new software. And we know all the things that apps “used to do”. And we want all sorts of other bells and whistles. And we’re wrong.

As a developer, you should be very careful about this early feedback for your app. Simplicity is the name of the game in this new world order. You don’t maintain simplicity by adding tons of features.

Two of the most requested features after the 1.0 release of Twitterrific for iPad were Instapaper support and photo uploading. If you think about these things, both have a high cognitive load. To use Instapaper, you need to know that:

  • The service exists, and that you can signup for an account.
  • That you can install a bookmark and use it to save pages from your browser.
  • That these saved pages can be synced to your iPad using another application.

For photo uploading, you have to know how to do one of these things in order to “get a picture”:

  • Use the camera connection kit to transfer photos, or
  • Take a screenshot with a non-intuitive gesture (the power and home buttons), or
  • Tap and hold on a picture in a web page and save it to an album, or
  • Create events in iPhoto and sync them with iTunes

Ask yourself if you could explain any one of these things to your mother in less than 25 words. I know I can’t and I’m pretty good with this kind of stuff.

Of course, these are both useful features and we added both of them in subsequent releases. In the case of Instapaper, the feature doesn’t even show up in the UI until you go into the Settings app and add your account information. My mom will never see it.

Photo uploading is a simple button on the compose screen that lets you choose a photo from your library. Eventually, our mothers will figure out how to add things to the photo library and use that feature. But they’ll be happiest when a future device let’s us put a “Take Picture Now” button on that screen.

It’s very easy to get caught up in the excitement this new device has generated in the last month and a half, but the real thrill will be in a year’s time when people who’ve never used a computer will be telling you how much they love your app. And there will be a lot more than 300,000 of them…

Updated: Check out similar thoughts from my colleages: David Lanham and Gedeon Maheux.

Communal computing

Dear Steve,

First, let me congratulate you and everyone at Apple on the release of the iPad. From my dealings with your company, I know it wasn’t easy. Thanks to everyone for busting their asses: a lot of very complex puzzle pieces came together during those last 60 days!

I recently had an encounter with Bill Atkinson. I told him that “I haven’t had this much fun with a computer since 1984.” He laughed, said “Thanks!”, and went back to working on his iPad app. We, and many other developers like us, are completely smitten with this new device.

After owning an iPad for a little over three weeks, it feels like we’re dealing with something much bigger than that Mac we all got excited about over 25 years ago. I’ve been struggling to define exactly what that is: beyond the technical specifications like the beautiful screen with its large multi-touch surface. Those specifications define what the device can do, but not what it means in our lives. I want to understand the magic.

Last week, much of that meaning came into clearer focus at a birthday party for my brother, niece and nephew (April is birthday month in our family!) My wife had loaded our iPad with photos from a recent trip to see the desert wildflowers in Anza Borrego and my 50th birthday party from the week prior.

Predictably, people’s initial reaction was “Wow, that’s the new iPad!” But that quickly faded as I opened the Photos app and passed the device around. My family was more interested in sharing the photos than talking about the new technology.

I was particularly interested in how my mother, the quintessential technophobe, would react to the device. She picked up on things quickly and was flipping through photos in no time. It astonished me how the interface disappeared for her: at one point she subconsciously licked her finger before “flipping” to the next photo.

As interesting as it was to see someone non-technical use the device, the real eye opener was how several people could interact with the iPad at once. Much of my mother’s fear of computers was overcome because she was looking at the pictures alongside my sister-in-law who helped her out when she got stuck. Learning was organic.

My niece also discovered some of the games I had on the device. One, Abca, was a hit because many people could play it at once. I’ve always played the game by myself and was surprised at how much fun it was to have other people guessing words simultaneously. A group of people transformed the software into something no developer had ever expected.

All of this led to the revelation that we’ve begun a new age of “communal computing.” The desktop revolution centered around empowering individuals: this new revolution will extend that empowerment to groups of people.

The iPad was naturally passed around amongst the partygoers. Many people interacted with it during the evening, and I lost track of who had it at any given time. And therein lies a fundamental problem.

My iPad has a lot of personal information on it: email, business documents, and financial data. When you pass it around, you’re giving everyone who touches it the opportunity to mess with your private life, whether intentionally or not. That makes me uneasy.

It’s hard to fault Apple for this shortcoming. The secrecy of the project undoubtedly limited the amount of group interaction your designers and engineers would experience with their new creation. The social aspects of this device is probably just as much as revelation to them as it is to me.

I can envision several ways to solve this problem: either with a traditional login screen or with something new like folders that require a passcode to open. I have no doubt that your designers can find something elegant that gives me peace of mind as I share my iPad with friends and family.

Thanks for your time and consideration,

Craig Hockenberry

Updated April 30th, 2010: I filed Radar #7922808 for this issue and it was marked as a duplicate of Radar #7584426.

Of toolbars and actions

Another area where I find iPhone development to be a bit convoluted was with toolbars and action sheets. The sheets are conceptually tied to the toolbar, yet there is no glue to combine UIActionSheet with UIToolbar. It’s also fairly difficult to represent your application state in the toolbar—an example is the refresh button in Twitterrific that turns into a cancel button while the refresh is taking place.

And then one day it dawned on me: an iPhone toolbar with an action sheet is like a menubar with menus on the Mac desktop (turn your phone upside down and there is even some visual similarity.)

After investigating some of the design patterns for NSMenu and NSMenuItem, it was clear that this would work well on a mobile interface as well. My implementation is a subclass of UIToolbar named IFActionToolbar.

In it’s simplest form, you attach a list of items to one of the toolbar’s bar button items:

@interface MyViewController : UIViewController
{
  IBOutlet IFActionToolbar *toolbar;
  IBOutlet UIBarButtonItem *barButtonItem;
}

...
@implementation MyViewController  

...

- (void)viewDidLoad
{
  [super viewDidLoad];

  IFActionToolbarActionItem *actionItem = nil;

  NSMutableArray *actionItems = [NSMutableArray arrayWithCapacity:3];
  actionItem = [[[IFActionToolbarActionItem alloc] initWithTitle:@"One" target:self action:@selector(firstAction:)] autorelease];
  [actionItems addObject:actionItem];
  actionItem = [[[IFActionToolbarActionItem alloc] initWithTitle:@"Two" target:self action:@selector(secondAction:)] autorelease];
  [actionItems addObject:actionItem];
  actionItem = [[[IFActionToolbarActionItem alloc] initWithTitle:@"Cancel" target:nil action:NULL] autorelease];
  [actionItems addObject:actionItem];
  [toolbar attachActionItems:actionItems toItem:barButtonItem];

  [toolbar update];
}

The IFActionToolbarActionItem is just a simple wrapper object that associates a title with a target and action. These action items are used to automatically construct the action sheet when the user taps on barButtonItem. If you’ve ever constructed an NSMenu using NSMenuItems, this will feel quite familiar.

Additionally, the toolbar supports an -update method. This method calls the assigned delegate to enable or disable toolbar buttons, set the image for the toolbar item, change the title of the action sheet, hide or show items in the action sheet, and define the cancel or destructive buttons in the sheet. Again, similar in pattern to how NSMenuItems are maintained.

Any time you call this update method, the UIToolbar is configured automatically. It makes it much easier to reflect the state of your controller in the view.

I’m not going to spend too much time discussing the inner workings of this class: the picture of a sample project is worth a thousand words.

One thing I would like to caution you about: don’t get too carried away with enabling and disabling items in the action menu. In our UI testing, we found that changing the list too much was confusing for users. It’s like the “adaptive menus” used in Microsoft Office: it’s very difficult for a user to adapt to your interface if it’s constantly changing. Just because you can doesn’t mean you should.

Again, I hope this code is useful in your own iPhone projects. Enjoy!

Matt Gallagher deserves a medal…

Every once in awhile you read a blog post that completely changes the way you think about a problem. Matt Gallagher’s Cocoa With Love is one of those blogs where it happens often. If you’re not subscribing to his RSS feed, do it now.

In particular, this post addressed a problem that every iPhone developer has encountered: any kind of settings or form UI is a pain in the butt if you follow Apple’s sample code. And, of course, this is exacerbated because these essential interfaces aren’t very fun to code. For both Twitterrific and Frenzic, it’s been a frustrating experience: I wanted to fix how this standard UI was created and maintained.

The motivation

Before I start talking about what I did using Matt’s concepts and code, I’d like to discuss the need for settings in an application.

There are some people who think that settings should only be in the Settings app. There are others that think they should only be within the application. I can honestly see how both groups are right, but what both sides fail to realize is that it’s often a matter of context.

If you’re working on a simple application with simple needs, relying on the infrastructure provided by the SDK is fine. You may have some additional support load for users who have problems finding your settings, but that’s a reasonable tradeoff for saving development time. Sophia Teutschler’s Groceries app is a fine example of where the built-in settings shine: I turned off the Marker Felt font several months ago, and I haven’t touched it since.

In the case of Twitterrific, there were three main reasons why we built the settings into the application:

  1. We could not split the settings between two locations. From a user’s point-of-view, it’s incredibly confusing to have an application’s configuration in two places. This would have happened if we had put the account settings in the application and everything else in the Settings app.
  2. Some of the settings are things that people will change on a fairly frequent basis. For example, the dark theme works best at night, while a light theme is better during the day. Leaving the app to make these types of adjustments is inconvenient.
  3. The Settings app can’t handle preferences that are “dynamic.” An example is a vibration setting for the notification: there’s no way to make this appear on an iPhone but not on an iPod touch.
As we start to see more complex applications appearing on the App Store, I think there will be a lot of other developers coming to grips with settings in their applications. That’s where my code comes in…

The solution

I’ve taken the basic concepts that Matt presented in his article and extended them to create a pixel perfect replica of what you see in the Settings application. Instead of configuring applications using a property list, you do it with some very simple code in a view controller. (Domain-specific languages, such as those found in Ruby, were an inspiration for the methods used in this code.)

And if you’re not doing settings, the classes are still very handy for making user input forms. They were used in all of the search forms used in the new version of Twitterrific.

To give you a quick taste of how it’s used, here’s a complete implementation of a table view controller that presents a single group with a text field and a switch control. In just six lines of code:

- (void)constructTableGroups
{
  NSMutableArray *cells = [NSMutableArray array];
  IFTextCellController *textCell = [[[IFTextCellController alloc] initWithLabel:@"Text" andPlaceholder:@"Placeholder" atKey:@"sampleText" inModel:model] autorelease];
  [cells addObject:textCell];
  IFSwitchCellController *switchCell = [[[IFSwitchCellController alloc] initWithLabel:@"Switch" atKey:@"sampleSwitch" inModel:model] autorelease];
  [cells addObject:switchCell];
  tableGroups = [[NSArray arrayWithObject:cells] retain];
}

The real beauty of this code is that it’s incredibly easy to change. Settings and forms tend to evolve over the lifetime of a project, so using these simple declarations for the table view layouts makes it much simpler to adapt to new requirements. If I need to change the switch control shown above into a choice list, I can do it in a couple of lines of code.

So without further ado, here’s the source code in a sample project. The code is well documented, so you shouldn’t have any problems figuring out how it all works. Start by looking at the RootViewController, then take a look at the SampleViewController, followed by the SampleAdvancedViewController. If you’d like to incorporate this code into your own project, just grab all the classes with the Iconfactory prefix (“IF”.)

The license

Previously, I’ve released source code on this site without any licensing at all. This time, I’m going to try something new. You can do anything you want with this code with one requirement: you need to give the Iconfactory some link love in your product.

For more details on the licensing terms, check out the Licensing.rtf file that’s included in the sample project. If you can’t abide by this restriction, please get in contact and we can try to work something out.

I hope this code saves you as much time as it has saved me. Enjoy!