Introduction
Isn’t it ironic how verbose ObjC is, and yet Apple’s developer forums is shortened to “devforums”? I think people can easily advocate verbosity, but are subconsciously sick of it … Oh well, onto the post.
Crash and Burn
As my app crashed and burned when I released it to the AppStore, I had no choice but to blame Swift. For example, one of the crashes was due to some dealloc race condition, and was easily solved by moving away from closures. That established a rule in my head “Closures are tricky, Swift is not to be messed with”.
Unfortunately, I had another crazy crash, and that one was actually happening on launch. Here is the sad part .. Even after making sure I am capturing startup crashes, I couldn’t do anything about it! The crash stack trace was so ambiguous and vague, I had no idea what was going wrong.
I noticed that I was using FBKVOController
in the crashing method, so I thought “Oh no! That again!”. I removed that code, and was ready to submit my app to the store. Luckily, one of my users reached out and was willing to do a test run of the patched app, to see if it works. It didn’t…
I tried a few other changes in the code, then gave up. I just had to do some proper research, surely I’m not the only one left with a vague swift crash! As expected, I wasn’t.
Over at the Apple devforums, a gracious user pointed out that my problem was because Swift doesn’t provide accurate crash backtrace… Say what?
Swift does not provide accurate crash backtrace
Daaaaamn .. Seems that Chris Lattner and the Swift fellas decided to optimize the hell out of the compiled swift code, and that meant when a crash happens, all you get is that it happened in which function!
That may sound reasonable, but for my app it wasn’t. My function was viewDidLoad
, and I setup a bunch of observers there, as well as interact with an ObjC library. That library returns a bunch of time bombs, aka implicitly unwrapped optionals. Any one of them could be crashing!!
In short, I was able to send a debug build to the user, and finally found the crashing line .. But still didn’t figure it out immediately, and felt really stupid (X_X)
.
The crash was ultimately a string that I never, not in my wildest dreams, thought it could ever be nil
! The string was being returned from the ObjC library, and the library was trying to localize the string. The localization broke with certain device language … Daaaaaaaamn.
Conclusion
I realized how dangerous it was to have all my swift code call the ObjC library all over the place without proper assertions and linting. From that crash, for example, I ended up throwing an exception if the app couldn’t localize a string. At least I can read that exception and fix it if it ever happened again …