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.

Frustration

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.)

Also:

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.

And:

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.

Before the Gold Rush

I ran across an old post of mine from 2008, before the App Store opened: The Coming Gold Rush.

One prediction — almost a gimme — is that we’ll see tons of to-do lists and Twitter clients.

Also:

It’s possible the App Store will have user comments, but it’s unlikely that it will have high-quality reviews.

Ramblin’ Nick

Nick Bradbury on laughter, middle age settling, and farts:

Hope, unfortunately, can be hard to hold onto the more you learn about the world. That seems to have been a problem for some of the dark humorists I’ve enjoyed.

Meta

First, a reminder — WinterFest 2014, the festival of artisanal software, is still on. You can get 25% off some great indie apps for thinkers and writers.

WinterFest 2014 is the sponsor for this blog this week, and it’s also the last sponsorship this blog will run, and it’s a great note to end on. (I love indie software and so do you.) After this there won’t be any more sponsors.

No Inessential readers have complained about the sponsorships, which made me glad. Booking was pretty easy. But dealing with all this is more work than you might think — and, more importantly, it doesn’t fit with how I think of my blog, which is my labor of love. So I’m stopping.

I’ll continue to run ads from The Deck, though. It’s different because it’s different.

But anyway — that’s the scoop. No more sponsors. (Unless somebody offers me a crazy amount of money, that is. Because doi.)

To all the folks who sponsored this blog this year: thank you so much. It was very appreciated.

Interface Builder Again

This post of mine, almost two years old — How Much, or How Little, I Use Interface Builder These Days — was referenced on Twitter recently.

It’s worthwhile to revisit these old posts when things change. And my use of Interface Builder has changed quite a bit since writing that post.

Here’s what’s changed:

Auto layout has become more and more a required thing. Recently I was doing layout the old-fashioned way on OS X — using resizeSubviewsWithOldSize: — and, in the specific context where I was using it, it didn’t work correctly. (The layout wasn’t actually updated without resizing the window or similar trickery.) This tells me that to stick with the old-fashioned method is to commit to frustration.

This would be terrible news, but Interface Builder’s auto layout support is much improved since that old post. It no longer creates unasked-for constraints as I’m working. That’s huge.

Some other good things have happened. We have storyboards on Macs now, which make it easier to manage things like preferences windows and login/create-account flows.

And we now have IB_DESIGNABLE and IBInspectable, which makes Interface Builder more useful for designers, which is great if you’re like me and want your designers to have as much direct manipulation as possible.

So. A few good things, taken together, tipped me over, and these days I use Interface Builder a ton.

Favorite Apps

On the Omni blog, several Omni employees write about their favorite apps of 2014. Waterlogue, MarsEdit (that’s mine), Overcast, 80 Days, Prompt 2, BBEdit 11, Aeropress Timer, Editorial, and Pinswift.

Bill Talk

Omni design idol William Van Hecke’s talk from CocoaLove — Your App Is Good and You Should Feel Good — is up on Vimeo.

[Sponsor] WinterFest: the 2014 festival of artisanal software

Your writing doesn’t come from a factory. Neither does artisanal software.

A bunch of small, independent software visionaries have teamed together once again this season to bring you fresh, opinionated, and exciting tools for thinking and writing.

  • Tinderbox: the tool for notes
  • DEVONthink Pro: your Mac paperless office
  • Scrivener: your complete writing studio
  • Nisus Writer Pro: the powerful word processor for OS X
  • Aeon Timeline: timeline tool for creative thinking
  • TextExpander: type more with less effort
  • Take Control Books: the answers that you need now

No bundles or games or gimmicks; just great software at a great price, right at the vineyard gate.

(PS Brent speaking. This is the last sponsorship I plan to run on my blog. And it’s a great one. My entire career has been about tools for reading and writing — and so the developers behind these apps are my spiritual kin. Also worth noting: it’s not a bundle. Buy exactly the apps you want, for 25% off.)

Safari in Your App

Bryan Irace suggests UIKit needs a Safari view controller:

It’d be wonderful if Apple provided a “Safari view controller” that developers could present directly from within their applications. This controller would run out of process and work almost exactly like MFMailComposeViewController and MFMessageComposeViewController already do for composing emails and text messages respectively. The app would provide the controller with a URL (and optionally, a tint color), but otherwise what the user does in it would remain secure and isolated from any third-party code, yet fully integrated with Safari.app and Safari controllers presented by other applications.

That’s officer thinking.

Designated Initializers

Local hero (and my co-worker at Omni) Tim Ekl writes about designated initializers and NS_DESIGNATED_INITIALIZER.

[Sponsor] Harvest - Plan Your Team’s Time

Managing teams is hard. Imagine it’s Monday morning and your team doesn’t know what they’re working on for the week. Plans change and schedules change with them. Spreadsheets weren’t built for this.

Harvest Forecast is a tool designed to plan your team’s time. Visualize schedules in Forecast and easily adjust them as needed. Forecast keeps your team’s expectations on the same page and helps you move projects forward.

As new projects come in, you’ll know who's available, and when to hire. Leave behind bloated spreadsheets and begin scheduling in Harvest Forecast with a free 30-day trial.

OmniFocus on Best of 2014 List

MacStories: Apple Posts “Best of 2014” App Store and iTunes Store Lists.

Through absolutely no effort on my part, OmniFocus for iPad and for Mac are both on the list. (My work on OmniFocus for Mac isn’t shipping yet.) I’m so proud of the team.

And I completely agree with Threes as game of the year. I don’t play games very often, but I’ve been smitten by Letterpress and, this year, Threes.

20 Years of Script Debugger

Mark Alldritt — one of my heroes, one of the people whose example got me into and excited about the industry — writes about Script Debugger’s 20th anniversary.

Note that it was originally developed “on a Mac SE/30 with 4MB RAM using Think C.” Imagine.

Archive

Ads via The Deck