OmniOutliner for Mac 4.2.1

It’s on the Omni website and will be on the Mac App Store once approved. (In a week, give or take, I suppose.)

I like this particular release a ton because we concentrated on fixing crashing bugs to the exclusion of almost everything else.

Ideally we’ve have zero known crashing bugs. OmniOutliner isn’t quite there, but it can see that promised land from where it stands.

Argument about crashes

You could argue that fixing crashes isn’t that important these days. The risk of data loss isn’t what it was, now that so many apps do auto-saving, syncing, and state restoration. And re-launching an app is much quicker than it used to be. (Remember the old days of counting the number of bounces in the Dock?)

So a crash is really just a slight annoyance, you could argue — and you could argue that users take the occasional crash in stride.

I understand the argument, and I disagree. Each crash means somebody got a little surprised and angry, even if only for a moment — and that’s hard to wave away. If you care about your craft, you care deeply that what you make never unintentionally makes somebody mad.

And it’s also notable that once a user triggers a particular crash, they’re fairly likely to hit it again. Maybe it’s something about their document, or their machine, or the steps they’re taking to accomplish a certain task.

That person won’t be slightly annoyed at the second and third crashes. That person is — quite rightly — going to email support, particularly if the crash stops them from completing their work. So now the crash, however rare, is costing the developer time and money. (If you don’t buy the craft argument, you should buy this pragmatic one.)

Software doesn’t have to crash. You may think that it’s an idealistic goal, but it’s not — it’s do-able (I’ve done it; other people have done it), and it matters.

Video Interview with Mark Alldritt

Mark Alldritt has been one of my indie heroes for 20 years. In this interview he talks about, among other things, his work with AppleScript and Illustrator.


My friend and co-worker at Omni Dan Segars released SpotFunds, his first iPhone app, not long ago.

Keep track of just how much you’re spending on coffee (and similar). It’s an absurdly high amount. But you won’t know that till you get SpotFunds — the $3.99 app that saves you money.

(Note to Dan: there’s your marketing text, right there.)

Dave Winer’s idea was to build a system where his friends could recommend specific episodes of a podcast and they’d be displayed on a single page. And then you can listen to things — good things, hopefully — that you wouldn’t have heard otherwise.

If you’re in a podcast bubble, this is a way out.

OmniOutliner 4.2

OmniOutliner 4.2 is available direct from Omni. (It’s been submitted to Mac App Store but isn’t up yet.)

I don’t think I’ll make anyone too terribly sad if I say that it’s my favorite Omni app. I use it for a bunch of different things — outlining app architecture and features, presentations, articles, and so on. Things that later end up in Xcode or Keynote or BBEdit start out in OmniOutliner. It’s where I think and organize.

Highlights: the new release (here are the release notes) updates the look for Yosemite and fixes a bunch of crashing bugs.

I’m proudest of the crash bug fixes — crashing sucks, and fixing crashing bugs is fun. (Sincerely. I enjoy the detective work.)

My theory about crashing bugs is that they cost more than most developers think they do. They cost you in goodwill (users hate crashes; users don’t think of crashes as acceptable inconveniences) and they cost in support and QA time.

In my ideal universe, all developers everywhere would prioritize crashing bugs over everything else, all the time.

Dave on Silo-Free Software

Scripting News:

I guess you could say I believe there are other reasons to make software, other than making money. Some people like to drive racecars when they get rich. What I want is to drive my own Internet, and for you to drive yours too.

Two Apps

My friends Chris Parrish and Guy English just released Napkin 1.5, a huge update to their already-awesome visual markup app.

And cousin Michael and team just released Fantastical 2.0. You already know about it and you’ve bought it. I’m just reminding you that you have good taste. :)

OmniOutliner 4.2 Public Test

OmniOutliner, on Twitter:

OmniOutliner for Mac 4.2 public test builds are now live! Contains Yosemite UI updates and other bug fixes.

I’ve been helping work on OmniOutliner, mostly on updating it for Yosemite. There’s plenty more to do, but some of the obvious things — vibrant sidebar, new-style toolbar buttons — have been done.

OmniOutliner is the first Omni app I started using (many years ago), and it’s still my favorite.

If you’re not faint-hearted, and you’re an Outliner fan, then please grab the test version and help us make sure this release will be awesome.

New Blogging App: MyWord Editor

MyWord Editor, from Dave Winer, is a “a simple silo-free blogging tool that creates beautiful essay pages.” It’s open source.

The announcement page has an aside about RSS that I enjoyed:

Of course every MyWord user has a great full-featured RSS 2.0 feed. We love RSS and it feeds us and we feed it, it's doing great, and anyone who disses it is a mean rotten silo-lover.

NSSegmentedControl with Menus

Mac developers: you probably recall that you can set a menu for each segment in an NSSegmentedControl, and the menu appears when you click and hold.

The problem with that is discovery — there’s nothing that shows that there’s a menu there.

So here’s what I want to do: put a downward-pointing arrow or chevron graphic to show that there’s a menu. And make it so that if you click on the arrow directly, you don’t have to click-and-hold.

But I don’t want to an entirely custom thing: I still want to use NSSegmentedControl.

What’s the best way to do this? Just place arrow buttons on top of the NSSegmentedControl?

I figure I can draw the arrows easily enough by subclassing NSSegmentedCell — have drawSegment:​inFrame:​withView: call super and then draw the arrows. But drawing isn’t enough — I want to have an actual button so you don’t have to click-and-hold.

Yet it seems weird to just place buttons on top of a control. How would you do this?

Three Down, One to Go

I was an Omni fan for many years before joining the company. It’s not just because the apps are so good — it’s also because it works like this: imagine what the right thing to do is, then watch Omni do it.

Right now the right thing, for our users and for the good of the apps, is to make them all universal — and as free upgrades for the iPad versions.

We just released OmniOutliner universal. It joins OmniGraffle and OmniPlan — with OmniFocus next. (Which people all around me are working on.)

We’re on a roll.

(Me, I’m not helping at all with this universal stuff. I take no personal credit. I’m in Mac-land — my home! — doing Yosemite updates and fixing bugs.)

NetNewsWire Status: Everything I Know

People ask me — on Twitter, in person, in chat, via email — how NetNewsWire is coming along. (I just got another email this morning.)

Answer: I don’t know. Yes, I do see Black Pixel employees in person once or twice a month, but they don’t tell me. (The employees I see don’t necessarily know. But, if they did, it wouldn’t be right to talk about internal stuff like that, so they don’t.)

All I know is what I read on Twitter:

We are still working on NetNewsWire, but don’t have any timeline information to share about future updates.

NetNewsWire was sold to Black Pixel in June 2011. It has been updated: at least one 3.x update to the Mac version, and a Mac 4.0 beta program.

I did, at one point (last Summer, I think), contact them about buying it back, and Black Pixel declined right away (we didn’t get as far as discussing terms). (It would have been a great story, right? NetNewsWire and I go from Ranchero Software to NewsGator; NetNewsWire gets placed safely in Black Pixel’s hands as NewsGator turns into an enterprise company; NetNewsWire returns to Ranchero Software.)

And that’s all I know.

I’d still be interested in buying it back, but I strongly suspect this is off the table, or so expensive that it wouldn’t make sense. (The expensive part isn’t the code, it’s the name.)

What I would have done with it: Mac version only. Syncing would be via Feedly, Feedbin, etc.

The idea is that it would be easy to get into — since it would sync with something you’re probably already using — and it would be easy to mix-and-match. You could run NetNewsWire on your Mac and Unread on your iPhone. (I use Unread: I’m a fan. There are other good readers, too.)

I’d make it a for-pay app, probably $24.99 or thereabouts — and not really worry about it making money. (Because I wouldn’t need it to, and because I’d be working on it with a more powerful motivation: love.)

Black Pixel could take the above as unsolicited advice: go Mac only, and sync with an existing service. One developer and an occasional designer could do this.

But I suspect they’ve made other choices, and development is probably pretty far along — so, instead, I’ll just relax and let them surprise me. There are great developers at Black Pixel, and I stand by to be delighted.

OmniFocus, Vesper

OmniFocus 2.1.1 for Mac shipped yesterday with some crashing bug fixes.

And a universal version of Vesper shipped a couple weeks ago.

If you’re counting — and of course you’re not — that’s three shipments I’ve been involved in this year so far (counting the earlier OmniFocus 2.1). I’ve got a busy year planned. With perhaps a surprise in there. Feels good.

(“Feels good,” I say — I’m trying to give myself a pep talk. I’m home with a head cold, and everything feels bad at the moment.)

PS I’m working right now on a Yosemite update for OmniOutliner. OmniOutliner for Mac has been and remains my very favorite Omni app.

And that’s in part because I love outliners. My history with outliners goes back to 1995. (Example: 15 years ago I wrote C code for reading/writing OPML. I don’t link to it because there’s something to learn from the code — there isn’t — it’s just remarkable to me that I’ve been doing this kind of thing for so many years. It’s because I like it.)

Swift Blocker

I did some work to switch Vesper over to frameworks. In a framework I built for FMDB, a public header file has the following line:

#import "sqlite3.h"

That’s not allowed by default. But there’s an Xcode setting for it: “Allow Non-modular Includes in Framework Modules.”

This setting is the user-friendly version of CLANG​_ALLOW​_NON​_MODULAR​_INCLUDES​_IN​_FRAMEWORK​_MODULES. Here’s what Xcode’s Quick Help has to say:

Enabling this setting allows non-modular includes to be used from within framework modules. This is inherently unsafe, as such headers might cause duplicate definitions when used by any client that imports both the framework and the non-modular includes themselves.

Okay. I understand the issue and I’m willing to press the button — and I did, and everything works. Great.

Well, until I added some Swift code that imports that framework. Then I get the error:

Include of non-modular header inside framework module 'FMDB.FMDatabase'

Swift apparently doesn’t respect the CLANG​_ALLOW​_NON​_MODULAR​_INCLUDES​_IN​_FRAMEWORK​_MODULES setting, while Objective-C does.

Filed as rdar://20184784.

The bug report includes a small sample project that you can download:

Why I’m blocked

The VesperData framework — where VSNote, VSTag, and VSAttachment live — depends on QSDB (similar in purpose to FCModel) which depends on FMDB.

The upshot is that I can’t write any Swift code that references the data model. Which doesn’t leave me a whole lot else. (Given what’s already completed or at least started as Objective-C files.)

(Half of my friends — Gus included — are shouting at the monitor that this is a feature of FMDB and I should take it as a sign.)

One Way to Do Surveillance

This idea doesn’t require a hacked Xcode.

Create a shell company that pretends to be a small software development company.

Write an app for your intended audience — for instance, write a Twitter client for Arabic speakers. (Or Farsi. Or French. Or English.)

Add your surveillance framework to the app.

Make it a good app, something lots of people would like to use. Make it free. Spend money on marketing.

Buy lots of hard drives to store all the text, images, and metadata it captures.

Russian Jokes

Back when Russian communism was still a thing, sometimes here in the States we’d hear of the jokes Russians told each other. (“In Soviet Union, TV watches you!”)

And we’d think that our system was better since we didn’t have to joke that way. And we were right.

But today I heard: “It’s not NSApplication — it’s NSA-pplication!” (See today’s news.)

We make Russian jokes now.

Behind the Office Doors

For the latest I wrote Inside Omni, a quick tour of Omni’s infrastructure for managing large projects.

The entire issue — iOS at Scale — is worth reading. As always.


I’ve been doing this for years when I have a static thing and I want to set its value once:

static MyThing *foo = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
  foo = [some thing];

But lately I’ve been doing this:

static MyThing *foo = nil;
if (!foo) {
  foo = [some thing];

The advantage of dispatch_once is that it’s thread-safe — it’s one less thing to worry about when worrying about concurrency.

But here’s the thing: almost all of the code I write runs on the main thread only. And, furthermore, when I use this pattern it’s almost always in UI code (which is main thread code). (For example: initializing a gradient that won’t change and should be kept in memory.)

So dispatch_once isn’t valuable in those cases. And, worse, it could hide bugs. (If my main thread code isn’t running on the main thread, I need to see some problems as a result.)

I’ll keep using dispatch_once in the ever-more-rare cases where concurrency is actually an issue — but, where it’s not, I’m back to the old-fashioned way.

And the old-fashioned way is less code and easier to read, which I don’t mind at all.

Hard Syncing

I can’t stand to read App Store reviews (mine or anybody else’s) — but I was told earlier today that Vesper had a one-star review where the reviewer suggested we use WebDAV syncing.

Sure, we could do that — I thought — if I spent a year on that and did nothing else.

I also work on OmniFocus, which has WebDAV syncing, and it lets you use your own server or Omni’s. For free. This is a great feature, especially for companies and institutions required to keep all data in-house.

But here’s the thing: syncing is relatively easy if you treat it as a species of web services. That is, if the server side is a smart server with an API and a database, it’s not that bad. (Syncing is still hard, but this is the easiest way.) This is how we do it with Vesper.

Syncing by reading and writing files on a generic storage system, on the other hand, is much, much harder. It’s to Omni’s massive credit that they did this.

It’s not just harder to write, it’s also harder to support, since servers will have bugs or be misconfigured. But Omni has the resources to handle this.

This goes back to the discussion of Sustainable Software. Features are economic decisions.

Say I looked at it more closely and decided we could do it in six months instead of a year, including at least a month-and-a-half of concentrated beta testing with lots of different servers. We ship in six months (with no other updates during that six months, and definitely no Mac version). We raise the price to $24.99. We hire a support person.

If it were you, would you take that risk?

Misinformation part two

I updated Beware of Flags with some additional information. (Scroll to the bottom.)


Ads via The Deck