Gettin’ Serious About Screenshots

I’m putting on the finishing touches of new versions of Otto’s Remote and Antenna. One of the primary features of these updates is localization. The good folks at iCanLocalize are providing French, Italian, German, Spanish, and Simplified Chinese translations. One or two other languages may also be coming in the near future.

BabyGrow is also available in a small number of languages, but for it I never had the marketing material translated. This was probably a mistake, one which I am not going to repeat with Otto. And of course, if I am going to have the marketing copy localized, then it makes sense for the screenshots to be localized, too. For Remote, I provide four screenshots. Four screenshots across at least six languages is a lot of screenshots – and a lot of work to put together. So, I set about to try to simplify the process as much as possible.

First, I wanted a way to have dummy data to populate the screenshots. So far, I had been setting up scripts on the various Macs in my home before taking the screenshots, removing or renaming actions I actually use for ones that I hope are more appealing to a broad audience. Then, once screenshots are done, I go back and set things up the way I actually like them for my daily use.

Fortunately, both Remote and Antenna are designed to allow different backends, replaceable at compile time. This is an artifact of a time early in development when I hadn’t yet settled on using iCloud for communication. A few weeks ago I was considering getting rid of this extra layer of abstraction since it introduces a bit of busy work from time to time, but I decided not to and now I know it was the right decision. I created a new backend which simply loads a set of static data from a plist. This dummy backend is enabled by a new build configuration in Xcode. BabyGrow has a similar mechanism.1

Data taken care of, I still needed a way to produce 24+ screenshots for Remote. I recalled reading about using Instrument’s UI Automation for the task a few months back. After a bit of searching around, I found what I was looking for. Jonathan Penn put together a set of scripts which helps automate this task and put them on GitHub. Of course, the UI Automation script needs to be customized for each app. This was an interesting and frustrating experience, but within an hour or so I had a script to produce all of the required screenshots for the iPhone version of Remote. Unfortunately, I had some trouble getting things working in the iPad version:

So, it appears to me that UI Automation is currently completely nonfunctional on the iPad. (ADN)

Then, a while later:

Hey, so what I said earlier about UI Automation on iPad… Yeah, forget I said it. Ahem. (ADN)

Turns out, I am ashamed to admit, the current iPad version of Remote does not appropriately support the accessibility interface. Not only does this hinder potential users with vision difficulties, but it also prevents UI Automation from working. I corrected this oversight, which benefits both me and users of Voice Over. That taken care of, I was then able to automatically produce a set of screenshots for Remote on both the iPhone and iPad. Excellent!

I was still not satisfied, though. The actions in the dummy data were not localized. As nice as it is to have all of the UI translated, the user data being in English was still a bit jarring, especially for the Simplified Chinese screenshots. To handle this, I took all of the strings from my dummy data and sent it off to iCanLocalize. I then added code to localize the dummy data plist. The last piece of that particular puzzle was the screenshot demonstrating that arguments can be passed to scripts. The string entered in the arguments text field was hard coded in the UI Automation script. I updated the script to grab the appropriate translation instead.

Now all of the screenshots are produced automatically and are fully localized. This left one last detail: the carrier string in the status bar. I honestly hadn’t thought about it too much until I recently heard someone talking about an app having a custom carrier string in its screenshots2. I neither wanted to advertise ATT by using raw screenshots from my iPhone, nor have plain old “Carrier” from the simulator. So back to Google I went, and I turned up this gist which allows you to replace the carrier string in your app. I added this to the screenshots build configuration and set it up to use my initials (ASM) for the carrier string.

Finally, after all of this, I can automatically produce a full set of attractive, localized screenshots from both the iPhone and iPad versions of Remote.

That leaves Antenna. Currently I have a single screenshot for Antenna with some text describing what it does. I haven’t been too happy with that solution, but honestly there is so little UI in the app that there’s not much to show. After thinking about it for a while, I decided to try to show instead of tell. It is, after all, an image, not a block of text. I haven’t finished it yet, but I am working on showing the app “in action” with a split screen (think old TV and film “telephone” scenes). I will likely be using PlaceIt, which is a great tool. I probably won’t be automating this for now, but it’s only six or seven screenshots so not as much busy work as the screenshots for Remote.

I’m looking forward to getting the new versions of Otto’s Remote and Antenna out the door soon, and am happy to have gotten this part of releasing new versions largely automated. We’ll see if it actually translates to more sales outside of the US!


  1. BabyGrow’s mechanism is actually a bit more complicated. If I just used a static set of data, then it would show in various ways. For example, the babies’ ages would keep increasing at each new version, but there would be no new data for those months. So, in the debug configuration there is an extra item in the preferences screen which allows me to generate a new baby of a specified age, with a specified number of entries. For each entry, the data points are selected at random from within a certain range of a specified percentile. I can generate reasonable looking data for skinny kids, chubby kids, and any sort of kid in between.

  2. I think it was John Gruber on The Talk Show but I’m not sure and have neither the time nor inclination to go back and listen through a bunch of podcasts again to find out for sure.