Author Archives: Thaddeus

Friends and Family Apps

When the App Store first launched, mere presence was enough to ensure at least some small amount of success. Today, things are much different. A great idea with good execution will still struggle to make a splash in the App Store, unless the stars are perfectly aligned. Even then, it’s usually more about who you know and the press you can drum up.

Here’s a conversation I had with Kevin Harwood last week:

Kevin: “How was the [Pactola] launch?”

Me: “Eh… I knew it was going to be light. It’s pretty niche.”

Kevin: “Friends and family?”

Me: “Yep.”

I wasn’t kidding; I knew full-well going into the project that I was going to have a hard time selling an application that provides a rest API for sending push notifications. There are similar free apps, and the target market is pretty specific. To make matters worse, I spent no time marketing or reaching out to press folks who might want to do a review. These are pretty basic things, right? You’re probably asking why I bothered to build the app.

Here’s a secret for anybody interested in iOS development: employers don’t care how many units you’ve sold on the App Store. They care about what you’ve built: how you did it, what you learned, the extra attention to detail you gave, and how all of those things can help their team.

So why did I build Pactola?

  • The server is built in Go. This was my first experience with the language.
  • Jenkins deploys the server automatically when I push to master. The iOS build is also on Jenkins to ensure I’m building from reproducible sources, and not just a point-in-time on my local workstation.
  • The deployment script relies only on SSH and bash, minimizing VPS setup time and overall dependencies.1
  • The iOS app uses Storyboards and Auto Layout (I’m coming off of two years where I was primarily focused on OS X development targeting 10.6 and up; no ARC, no Auto Layout, and no Storyboards)
  • Screenshots are automated, thanks to ui-screen-shooter. I had to learn about UI Automation and come up with a strategy for creating real data in the screenshots.2
  • I disciplined myself to write out tasks and issues, and then tracked them on a Trello board. When the tickets were all in the Done column, I shipped. I also have a nice backlog of future ideas and nitpicks.
  • I used Apple’s TestFlight system for the beta. This was my first chance to use it, and I got a good feel for how it compares to the legacy TestFlight system.3
  • I’ve now shipped an application that uses APNS and have a strong working knowledge of the system, its capabilities, and have some ideas for leveraging it in other apps.
  • I tried to stick to a Ninety Days rule, though I didn’t account for changing jobs.

So while I may not ship very many copies of Pactola, I’d say there are a few interesting things I could talk about in an interview. I’d highly recommend finding something you’re unfamiliar with and building your own Friends and Family app.

  1. Since Go apps are statically linked, there are no other dependencies on the host system; pactola-server runs on any Linux system once my keys are there to accept the ssh deployment.
  2. The app contains no extra magic for this, except for registering as a special known-device when running on the simulator. The server populates the data for that special device. And yes, there are Go tests for that special behavior.
  3. Given the end of the original TestFlight, that proved to be a good use of time.

iPhone 6 Plus: One Month Later

The iPhone 6 Plus is one of the most curious devices Apple has built in recent years. The largest iPhone ever built, it evokes a sense of awe, confusion, and concern. In some ways, it suffers a bit of an identity crisis in the iOS family, as it behaves like an iPad sometimes, but is also clearly an iPhone.

After carrying it for a month, I’ve returned to my beloved iPhone 5s as my carry device. Since most reviews are written after only a few days of usage, I thought it would be interesting to share some thoughts on the iPhone 6 Plus after using it exclusively for over a month.

I’m in the unique position of possessing an iPhone 6 Plus that I don’t own. I would probably be more biased toward the device if I had paid money for it. It’s liberating to be able to evaluate the phone without worrying about the regret that would come with a purchase I don’t like. I’m also very grateful to be employed by a company that is excited to explore new devices and technology, and that paid for the phone.

To be clear: the views and opinions contained within are mine alone.

The Good: Camera, Screen, Apple Pay, Battery

The camera is absolutely wonderful. Without question, the camera is what kept me from ditching the iPhone 6 Plus sooner. The camera produces the most vivid colors I’ve ever seen from a phone, and rivals a lot of the pictures we’ve taken with our DSLR. With minimal effort, it can capture moments precisely and beautifully, which is incredibly important and valuable to me as a parent. I snapped some wonderful pictures of my children this past month, and they’re some of the best photos I have in our library.

Good morning, Austin

A photo posted by Thaddeus Ternes (@thaddeus) on

The screen is staggeringly large, which makes the experience of some apps simply wonderful. I watched nearly all of the Dollhouse series on Netflix with the iPhone 6 Plus; it’s a fantastic device for watching TV shows, and is much more comfortable to hold than my iPad mini. The detail in HD content is astonishing, and the backlight has no problem producing a blindingly-visible image in almost all lighting conditions.

Over the course of a month, I had a few opportunities to try Apple Pay, and was always pleased with how simple it was to use. I’m excited for the future of payments with NFC, and I have enough confidence in the security of Touch ID to use the feature in places where credit cards have previously given me pause. 1

What I’ll miss most from the iPhone 6 Plus is the battery. I could carelessly leave the device unplugged overnight without a second thought; I routinely went over two days without charging the device, especially when using my desktop to stay on top of my Twitter timeline. The battery life is incredible.

The Bad: Size, Flickers and Glitches

The biggest2 problem with the iPhone 6 Plus is the unwieldy size. One-handed use is almost impossible for me, even with my typically-large adult male hands. I found myself constantly worrying about dropping the phone, which is something I’ve never had much concern over with my smaller phones. Of course, this anxiety probably lead to the increased fumbles I had with the phone.

The weather in Austin has finally cooled down enough that I’ve been wearing jeans for the past month. The iPhone 6 Plus fits uncomfortably in my jeans pocket. I don’t notice it when I’m walking around, but have to take the phone out when I sit at my desk, drive, or play with my kids. It presses into me when I sit, and is impossible to take out of my pocket once sitting. For somebody carrying a phone in a bag or purse, this probably wouldn’t be an issue, but using an iPhone 6 Plus from a pocket is awkward at best. I’ve always carried my iPhones without a case, and while a case may have alleviated some of the fumble anxiety, it would undoubtedly make the pocket experience even worse for me.

The phone also doesn’t fit in a lot of places that are convenient to set a phone. Two of my favorites are cup holders in the car and the small tray on HEB shopping carts. Cup holders make a great bullhorn while I use Maps to navigate my new city, and the shopping cart trays safely cradle my phone while shopping3, keep me from fumbling the phone in and out of my pocket. Neither of these stashes worked with the iPhone 6 Plus, simply because of the size.

While the dimensions of the device can’t be changed, there are some other issues that Apple can fix with software updates. The iPhone 6 Plus exhibits more flickering views, rotation glitches, and animation stuttering than I’ve seen with latest-generation hardware, even when running the latest iOS release.4 In fact, I’d dare say my 5s feels consistently smoother.

One of the most frustrating issues I ran into was the inability to swipe open the camera from the home screen; when I would try to open the camera, the home screen would slide up about half an inch, and then drop back down to fully-locked. I missed more than a couple photos because I couldn’t get the phone unlocked soon enough. This may have to do more with iOS 8 than the iPhone 6 Plus, which I’ll understand better as I get back to my 5s as a daily carry.

In a lot of places, the curved edges of the phone enhance the user experience. Swipe gestures to go back in the view hierarchy are wonderful on the phone, when they work. More than a few times, I had trouble getting the gestures to recognize, which is an issue I’ve rarely experienced on my 5s. The fit and finish of the device is really wonderful, and it compliments the software in a way only Apple can.

My Favorite Size

I’ve seen a lot of praise for the iPhone 6 Plus, and most of the favorable reviews echo what I found: the screen if beautiful, the camera captures stunning images, and the promise of simple, secure payments is here with Apple Pay.

I’d love to see Apple roll the great things about the iPhone 6 generation into a hybrid with the last generation: smooth edges, thin profile, expected camera improvements, and stunning battery life. In some ways, that’s pretty similar to the 5th generation iPod: thin, smoother edges, aluminum back, and a manageable size. A reasonable mix of the things universally loved with a compromise on the physical size would be a welcomed upgrade for me. Until then, I’ll stick with my trusty 5s.

Oh, and reasonable storage. 16 GB is nuts.

  1. The gas station where I used Apple Pay most often also required a signature, which showed a fundamental lack of understanding in the technology by some payment systems.
  2. Sorry… I had to
  3. And being rate-nagged at the grocery store
  4. 8.1.1, as of writing

Ninety Days for Evening Indies

Justin Williams posted a great essay a few months ago where he shares a good bit of advice:

“Do not spend more than ninety days on your 1.0”

Justin’s reasoning is simple: it’s enough time to get something decent built, but short enough to keep you focused on critical features. Ideally, you ship and follow-up with other great features. Worst case, you regroup and try again.

However, his advice is specifically aimed at folks who are gambling on a full-time project. What about Evening Indies?

Evening Indies?

I’m not an indie developer; I’ve had full-time work since college. The places I’ve worked have all compensated me fairly, and I’ve been blessed to have challenging, enjoyable work. In addition to providing for my family, these jobs have also helped bootstrap my entrepreneurial ventures. I’ve recognized my entrepreneurial spirit for over a decade, and I’ve kept it safely satisfied with side projects and hobbies. Sound familiar? That list of app ideas you keep stashed in Evernote is a pretty good hint, especially if you find yourself thinking about it during work.

I’m not a full-time indie. I’m an Evening Indie.

Even Less Time

Ninety Days is perfectly applicable to the Evening Indie, even though you’re dealing with significantly less time 1. Software markets (especially mobile) can change dramatically in three months. It’s possible you will have built the wrong app by the time you’re done. If you do manage to hold on to a market opportunity longer than that, you still have to compete with your own fatigue and real-life commitments.

It’s incredibly difficult to build a sustainable business independently. Even with his past experience, large user base, and beloved app, Justin couldn’t make Glassboard work.

Realistically, it’s impossible to build something that can sustain an individual (never mind a family) with 3-4 hours of work per day. What’s left is to build something fun and interesting, and to do so pragmatically. With even fewer hours to spend than a full-time indie, you have to be even more diligent to protect your time. Ship something nice and simple. If the idea is solid, your customers will ask for the 1.1 features. Move quickly with them and adapt with the market.

I checked last night – my current side project is 68 days old.

Feels perfect. Beta soon. Ship in November. Keep my day job.

  1. 10-14 hours a day seems pretty normal for the indies I know. I’m lucky to muster 3-4 in an evening

And we never will.

Tim Cook, writing on privacy:

Finally, I want to be absolutely clear that we have never worked with any government agency from any country to create a backdoor in any of our products or services. We have also never allowed access to our servers. And we never will.

Given the threat of fines Yahoo faced in 2008, this is a bold statement.

When Your SVN Username Is Different…

Here’s a quick tip for git-svn users struggling to find the perfect Google-foo for git-svn usernames.

If your svn username doesn’t match your local machine username, update the ~/.subversion/servers file to look something like this:

[groups]
repo01 = svn.company.net
[repo01]
username = thaddeus.ternes

Also, here’s a little hack I put together for cloning an svn branch with git without pulling the entire repo history.

iOS Configuration with .ini

It seems like an unlikely candidate, but I’ve recently started using .ini files for iOS app configuration. I know what you’re thinking: “Wait – are you talking about those text files on Windows?”

Yep, those.

Common Formats

Let’s have a quick look at some of the most popular options for expressing configuration in text format.

XML

Historically, XML is probably the most popular choice – it’s widely supported, well understood by most developers, and expresses hierarchy quite well. In fact, plists are most often represented in XML, so they’re a natural choice for iOS and Mac developers.

<configuration>
    <views>
        <view>
            <!-- displayed when app launches -->
            <name>main</name>
            <textcolor>#0000ff</textcolor>
            <backgroundcolor>#ff0000</backgroundcolor><backgroundcolor>
        </backgroundcolor></view>
        <view>
            <!-- contains copyright, version information -->
            <name>about</name>
            <textcolor>#777777</textcolor>
            <backgroundcolor>#afafaf</backgroundcolor><backgroundcolor>
        </backgroundcolor></view>
    </views>
</configuration>

JSON

JSON is more fashionable these days, since it translates to dictionary/map structures quite well, and is also supported in most modern runtimes. It handles types very nicely, including lists and nested objects. It’s also noticeably lighter than XML, which makes it great for sending over networks.

{
    "views" : {
        "main" : {
            "textColor" : "#0000ff",
            "backgroundColor" : "#ff0000",
        },
        "about" : {
            "textColor" : "#777777",
            "backgroundColor" : "#afafaf"
        }
    }
}

You’ll notice the lack of comments – one of JSON’s biggest drawbacks for configuration is not being able to place comments in a file. There are some parsers that will accept certain sequences as comments, but that’s highly variable. For what it’s worth, the following NSJSONSerialization example produces an error:

NSString *json = @"{ \"rawr\" : \"bam\" /* no comments */ }";
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
NSError *parseError = nil;

id obj = [NSJSONSerialization JSONObjectWithData:jsonData
                                         options:0
                                           error:&parseError];

NSLog(@"parseError: %@", parseError.localizedDescription);

Output:

parseError: The operation couldn’t be completed. (Cocoa error 3840.)

YAML

YAML is probably the least common, though quite popular within certain development communities. The syntax is very readible, and it’s arguably the best at representing hierarchy. It actually has quite a bit in common with INI, which makes it a compelling option for cases where .ini may be too light on features.

---
mainView: #displayed when app launches
    textColor: #0000ff
    backgroundColor: #ff0000

aboutView: # contains copyright, version information
    textColor: #777777
    backgroundColor: #afafaf

YAML has a large featureset, which is a contributing factor to the complexity of most parsers. YAMLKit looks like the best parser for Objective-C, but requires LibYAML. LibYAML is a classic configure/make/install project:

$ ./configure
$ make
$ make install

If you were already going to be supporting cross-platform software, this wouldn’t be a big deal (though you’d also probably not care about the Objective-C aspects either), but we’re specifically talking about iOS here, so this is a fair issue. Getting this built for iOS isn’t as trivial as the steps above, so roll up your sleeves for a cross-compile if you head down this path.

A Common Problem

Each of the examples above has a subtle problem that would cause most parsers to fail, typically leaving the entire document unusable. In each case, the error is so understated that it may only be caught by a runtime error.

  • XML: careful to properly close those tags!
  • JSON: curly here, curly there, and oops! too many commas
  • YAML: derp – whitespace requirements around comments

Of course, the delicateness of these syntaxes is ultimately up to the implementation of the parser in use (and how strictly it conforms to spec). As you’ll see in a moment, I’ve skirted around those problems by implementing the ini parser myself.

INI

Let’s see what an ini file looks like.

[mainView] ; displayed when app launches
textColor = #0000ff
backgroundColor = #ff0000

[aboutView] ; contains copyright, version information
textColor = #777777
backgroundColor = #afafaf

There are a few things to like about the .ini version of this configuration. The file is incredibly readible. I prefer the section headings to separate objects in the file. The syntax isn’t dependent on whitespace, so there’s lots of freedom in formatting. In fact, the syntax of ini is so simple that there are relatively few things you can do to break it. When things do break, they typically only ruin the current line, which doesn’t prevent the rest of the file from being parsed.

BTINIParser

Of course, it wouldn’t be fair to try and advocate such an absurd notion without giving you the chance to try it for yourself, so I’ve included BTINIParser in my BTToolkit project. It’s very much a work-in-progress, but includes tests and is powering a theming engine I’ve built into a little iOS project I’ve been working on. It could use a few more public methods, as well as some error reporting, so fork and submit PRs, please.

Try It Out

Hopefully this has piqued your interest in exploring an uncommon file format for iOS developers. If you’re working on an app that supports themes or other variable runtime definitions, it’s definitely worth a look. The ini file is a nice option that easily covers the key-value pair requirements of most configuration needs.

Let me know how it works out by chatting with me on ADN or Twitter.