Jan 2015

SCM Search

My co-worker and local hero Curt Clifton writes on Twitter:

Archiving 24,724 commit message emails to EagleFiler. Maybe Mail.app will actually perform reasonably after this. Fingers crossed.

Here’s the thing: this sucks.

At Omni, like many places, we get commit messages via email. (I have three filters and folders: one for mine, one for OmniFocus, and one for everything else.) It’s fine — email is a decent notification system.

The problem comes when I want to find something in a past commit message. Which happens all the time.

What I’d like is a commit-searching app that’s a desktop app (because I’m not going to remember yet another command line app’s arguments) that supports Subversion (which we use at Omni) and Mercurial and Git (both of which we use at Q Branch).

Were I to write this myself (I’m not going to) I’d probably use SQLite to store the messages and their metadata and SearchKit to make it searchable.

It’s possible that something like that wouldn’t work for Omni — with our hundreds of thousands of commit messages, a database on a server is probably better — but it would work for smaller teams.

Is this a money-making idea? I don’t know. But as a Mac app it would probably do better than whatever iOS app you were thinking of writing. (You’d get my money, at least.)

For the Glory

There are so many new buildings going up in Seattle — Boomtown — especially around South Lake Union where I work. And it seems that every in-progress building and every construction crane has a big blue 12 flag.

It makes me think of the religious art of the middle ages and Renaissance, except that our new civic religion is the Seahawks. As if all these buildings are going up as humble praise to our football team.

Which doesn’t make me sad. Go Hawks!

Gus on Microsoft and Apple

Gus Mueller, Microsoft, Apple, and Disappointment:

Apple is your favorite aunt or uncle, who isn’t talking about crazy future ideas, but is instead showing you how to hold a pencil correctly, or a tie your shoe. Something you can do today. Apple isn’t flailing about trying to grab onto whatever it can so, yelling out for attention. Apple is solid, reliable, dependable.

And I think that is why we’re seeing so many people reacting to Apple’s software quality lately. You expect Microsoft not to deliver. But we expect Apple to.

Wikipedia Draft Decision

Wikipedia’s Arbitration Committee [ArbCom] on Gamergate has produced a draft decision. Mark Bernstein writes:

By my informal count, every feminist active in the area is to be sanctioned. This takes care of social justice warriors with a vengeance — not only do the GamerGaters get to rewrite their own page (and Zoe Quinn’s, Brianna Wu’s, Anita Sarkeesian’s, etc.); feminists are to be purged en bloc from the encyclopedia. Liberals are the new Scientologists as far as Arbcom is concerned.


When Mac and iOS developers get together, we complain about Apple bugs — which will always be true, whether or not the number and severity of bugs is actually high.

If we can’t grumble, we can’t be happy. So we grumble.

If you and I were sitting at a table, here’s the story I’d tell you:

WebView has a bug where scrolling is messed-up in some cases where you have a div that needs to stay anchored to one side of the window. (Think of a header that doesn’t move while the rest of the content moves.)

But the new replacement for WebView — WKWebView — doesn’t have this bug. Which is great. Let’s adopt the new thing! I’m all in. Love new things.

So I did, and it’s great. So happy. Until I noticed the console message:

Could not create a sandbox extension for '/'

I did some research, and I learned that WKWebView won’t show local content — that is, files that are loaded from the app’s bundle. Files from the app bundle ought to be a-okay, ought not be a sandbox violation, but apparently they are.

So while this works fine in my development build, research tells me it won’t work for the release build.

Do I need to write and embed a small web server in the app just to make this work? (Na ga da.) Instead, let’s just put the files on the web, because of course the web is safer than files distributed in the app bundle. (That right there was sarcasm.) It means the feature won’t work when off-line, but there are mitigating factors that make that mostly okay. Okay enough.

So: great. Problem solved!

Until, that is, I went to wire up the Find command. WebView has a searchFor:​direction:​caseSensitive:​wrap:. It’s not as great as the Find feature in Safari, but it’s okay for what I’m trying to do. (At least for now.)

WKWebView has nothing even similar. So now I don’t know what to do.

In an ideal world, WKWebView would work with files from the app bundle, and, as a replacement for WebView, it would have the same functionality as WebView (a searchFor or equivalent method). Anything else means running as fast as I can while I slip backwards.

Daniel’s Refactoring

Daniel Jalkut wrote about his adoption of NSURLSession — by writing a new cover class that has the same interface as his existing url-downloading code (which was a cover for CFNetwork).

This is the right way to do it. The callers — including the unit tests — don’t have to know anything about the implementation, since the interface is the same. That’s just good programming.

It’s also not how I would do it in this specific case.

My thinking:

It totally makes sense to have a cover class for CFNetwork, since it’s C-based but we want an Objective-C class. (I use FMDB for a similar reason — so I don’t have to use SQLite’s C interface.)

But I don’t like wrappers for things that are already written in Objective-C. (I don’t like subclasses either, except in cases such as NSOperation and UIViewController that are designed to be subclassed.)

Instead, I’d rather just use a thing directly, rather than write a class that wraps a built-in class.

The difference may be subtle, so I’ll use an example. Consider an RSS reader that needs to download a bunch of feeds.

Before NSURLSession, I’d create an NSOperation subclass that downloads a feed. That subclass would use NSURL loading classes to download a feed and eventually call back somewhere with the result.

Now with NSURLSession, I’d create an NSURLSession and NSURLSessionDataTask objects to do the downloading. No NSOperation subclasses.

In both cases I’d have an outside class — RSDownloadFeedsSession or something like that — that would have an unchanging interface. But, importantly, RSDownloadFeedsSession wouldn’t be a general wrapper for NSURLSession. It would just be a thing (inherited from NSObject) that uses NSURLSession.

The goal, in other words, is to stay close to the frameworks. Because:

  • Other people can understand my code more easily.

  • I can understand other people’s code more easily since I speak the standard Cocoa dialect.

  • I don’t have to worry about the curse of shared-code-that-wraps-things — that a change fixes App A but breaks App B. (Yes, unit tests may detect the breakage, but the point is to avoid the possibility of breakage.)

  • I don’t have to worry about the other curse of shared-code-that-wraps-things — that it will accrete features and configuration and special fiddly bits until it’s difficult to maintain and no easier to use than the thing it wraps. (I’ve been down this road.)

But here’s a point worth making: every good programmer has their own style, the way that works for them. Which means that Daniel’s approach is utterly right for Daniel, as mine is for me. Part of the deal with becoming a good programmer is learning about yourself — learning what your style actually is, and being comfortable with it evolving over time.

Update the next morning: Daniel responds. Daniel and I are doing things the same way more than not, which should not be a surprise.

OmniFocus 2.1 Thrill-Seeker’s Test Build

The first of my work at Omni to get outside the office is the new beta of OmniFocus 2.1 for Mac.

Here are the release notes, and here’s a screenshot.

While this beta contains my work, and I’m proud of it, it’s not all my work — I’m one part of a big team that makes and supports great apps.

As always: if you have questions, problems, or feedback, please contact the Support Humans. They’re great, and they make sure things get in the system so that everybody knows about them.

Omni Group’s Report

Ken published Omni’s 2014 report plus 2015 plans this morning.

The company did what it planned to do last year, plus more, and it was a record sales year for OmniFocus, OmniOutliner, and for the company in general.

The app I work on, OmniFocus for Mac, was mentioned a few times. It’s in the App Store’s Best of 2014 — no thanks to me. :) (None of my work on OmniFocus has shipped yet.)


Yosemite brought a new look and feel to the Mac, so we’ll be updating all of our Mac apps to fit in well there. We started this process last year with OmniGraffle 6.1, but we’ll also be updating OmniFocus and OmniOutliner and OmniPlan. Yosemite also brought support for extensions similar to those on iOS 8, so we’ll be adding Today and Sharing extensions to OmniFocus for Mac when we update its interface.


OmniFocus 2 has been very well-received—setting a sales record in 2014—but in no way does that mean we think it’s finished! We’ve been listening to your feedback, and we will continue to update the app to make it sync more responsively, to be easier to scan visually, and to be more efficient to use.

That’s where I come in — helping to make this all come true in 2015.