On Fixing that NSNull Crasher in Overcast
I don’t normally head home after lunch, but today I was on the bus going back to Ballard, about to open iBooks on my phone and get back to reading The Caledonian Gambit (which I’m thoroughly enjoying), when I decided to check Twitter first — and saw Marco’s tweet about Overcast’s oldest crash.
I’ve written before about how I love fixing crashing bugs. Partly because I’m adamant that an app should, at a minimum, keep running — and also because it’s fun detective work. (I’ve even written a series of blog posts on how not to crash in the first place.)
So I took this one as a challenge. Here’s how I figured it out:
The exception reported
[NSNull doubleValue]: unrecognized selector. Now,
NSNullis a stand-alone code smell: there’s hardly ever a time where it should be used. Well, there was that one weird thing with the kerning a long time ago, but that’s about it. This crash is probably not that.
Then I looked at the backtrace and saw
-[NSRTFWriter writeKern], and then I looked a little further and saw that an
NSAttributedStringwas being exported to RTF, and, furthermore,
writeKernprobably is writing out the kerning attribute, which was set to
writeKernwas expecting an
NSNumber. So that was it.
The kerning attribute is NSNull. That used to be the way to specify use font-specified kerning.
And then Marco found the bug and fixed it.
* * *
This is a story about experience and luck, not brains. It’s just that I’ve been working with these APIs for a long time.
Here’s the story behind setting
NSNull. Back in the iOS 6 days, when John and Dave and I were working on Vesper — which used a custom font, Ideal Sans — we noticed that the kerning was fucking awful. We obviously couldn’t ship it like that. We had to either figure out how to fix the kerning or switch to the system font — which would have been heart-breaking, since Ideal Sans was so perfect for this app.
So I searched around until I found that there was a little bit of magic: in our
NSAttributedStrings, we needed to set
NSNull to get the font-specified kerning. I tried it — and it worked! We were able to ship with Ideal Sans.
(Here’s a search in Vesper’s code base for that attribute.)
I don’t know if this bit of magic is still needed these days. Hopefully not — because 1) it’s weird to have
NSNull have a meaning like this, and 2)
NSRTFWriter doesn’t know to expect an
NSNull instead of an
NSNumber (this should get filed as a Radar).
I no longer remember exactly where I ran across that bit of magic. Memory tells me what it was a slide from a James Dempsey talk somewhere, though I can’t seem to find it right now.
Anyway. This bug was fixed because years ago I was working with type nerds (and I am one myself), and because of James.
Fixing crashing bugs takes a village.