From a technical standpoint, my biggest skillset is in iOS development. Nonetheless, it occurred to me last week that I don’t have a terribly recent iOS project to show. As a consultant I wrote a ton of great code that solved my clients’ problems — but all that code stayed with my clients. The SIGILANCE card was my big personal project this year, but for that I was working mostly in JavaCard and Android. I very recently published the latest Bushwick Open Studios app, but even that was maintenance on a codebase I started in 2013. It’s still a solid app; it’s just not something new, and I was feeling the itch this weekend to make something new.
So I made TrainFace, a simple app that displays the status of the New York City subway system in an iPhone app, an Apple Watch app and a custom Apple Watch complication. I spent half of Saturday and half of Sunday on it, and you can check it out on GitHub here.
The rest of this post walks inch by inch through creating the app, linking to commits and showing screenshots at every stage. It’s fun to see how things get made, right?
Note to non-technical readers: a “commit” is sort of like a checkpoint in the process of writing code. I have links to these checkpoints throughout, but you don’t have to click on them; I explain what the code does right here in the post.
2:40 PM: First Commits
Every app has to start somewhere. In this case, the first commit is the most basic of basic iOS apps: a list view and a detail view. That’s not very exciting though, so in the second commit, I add some fake data to make it more interesting.
The next few commits aren’t much more to look at. Since you’ll probably want to prioritize the trains near work and home, I added support for reordering train lines. Also a label telling you when the data was last updated; boring, but necessary. The next commit is fun, though.
4:03 PM: Images and Colors
Given how colorful the screenshots are at the top of the post, you might be surprised to find out that there’s not a single image file embedded in the app. Commit number five adds support for generating subway icons right in the code. The whole shebang is a 57-line method in a category on UIImage. We look up the color of the line based on the MTA style guide, then use Core Graphics to draw the thing ourselves. Later, we’ll use this same method to generate assets for the Apple Watch app.
I’ve always been a huge fan of drawing art in code rather than embedding tons of images; with the explosion of form factors and resolutions, it’s not uncommon to have to embed dozens of PNGs for even a simple app. This app requires icons for 21 subway lines in three resolutions for two devices. Being able to do that with zero assets is a massive win.
Commit number six adds a splash of color to the main view, with color codes for the various levels of frustration a straphanger is likely to encounter. By this commit, the app is starting to look like a real app; all that’s missing is real data.
With the last commit on Saturday, we move from mock data to real data. In the rightmost screenshot above, the app is connecting to a JSON feed generated right here on my website. It’s based on the MTA service status API, but has some clever logic to parse out the status of individual train lines, and to boil long service advisories down to short, one-sentence summaries. That’s for another blog post, though!
Sunday, 1:49 PM: The Apple Watch app
After getting the app to connect to a live data feed on Saturday, it feels like a step backwards to make an Apple Watch extension filled with fake data. But in a lot of ways, the Apple Watch extension is an app all its own; you have to start from the beginning. In the first commit of the Apple Watch extension, I simulate a bad day at 14th and 6th:
The next commit adds commands to fetch live data and icons; all of a sudden, the app is starting to look like something real:
8:30 PM: Complications
There was a fair amount of sketching out designs for commit number thirteen. A “complication” is fancy word for a custom bit of information you display on the face of your watch. Complications are new to WatchOS 2, and they come in different shapes and sizes, from a tiny icon in the corner to a big centerpiece panel. For the moment, the app only supports one style of complication, the big one, which gives us three lines of text to work with. The app attempts to summarize as much as it can in those three lines:
Known issue: when switching from the two-line to the three-line table, the font weight changes. Not wild about that. Hey, it’s a first draft.
9:25 PM: Last Looks
Rounding out the functionality, it was imperative to implement a detail view for the Apple Watch interface; there’s no sense telling someone that there’s a service change unless you can explain what that service change is.
When the MTA publishes disruptions, they publish based on the trunk line that is disrupted; most apps that consume MTA data can only tell you that the ACE is disrupted. Since my feed can parse out disruptions to specific trains on the line, we’re able to show the disruption for the A separately from the disruption for the E. We’re also able to show only the most relevant information to the user; a one-sentence summary of the issue is a huge usability win when you’re glancing at your wrist.
Additional commits later in the evening add support for background refresh and implement refresh logic for the complication, but by 9:25 PM, the weekend app is done.
It’s nice to have a reminder that you’ve still got it. This weekend app reminded me how fun it is to code for iOS, and introduced me to some bleeding-edge features that aren’t even out of beta yet. Is it a polished app? Of course not. But it shows what I’m capable of doing in a couple of days.
Now that the crypto project is launched and out in the world, I’m excited to get back into iOS development. It’s where I live. It’s what I’m great at.