We’ve been updating the Bipsync Notes app to take advantage of a feature new to iOS 9: Storyboard References. Storyboards are Apple’s way of defining an app’s UI through a visual tool called Interface Builder, and the new Reference functionality allows app developers to break their Storyboards up into discrete manageable chunks which can easily be included from other Storyboards. It’s been long awaited from developers in the iOS community, and should spell the end of the kind of monolithic Storyboards we’ve all been accustomed to.
I’ve been working on separating the various screens of our app into smaller Storyboards. Thanks to Interface Builder’s “Refactor to Storyboard…” feature this was going really smoothly, until recently a strange behaviour was observed in the app: notes were being opened in the “master” view of the app’s split view controller, rather than in the “detail” view as they should.
I was pretty certain I hadn’t caused this by a deliberate change to the app’s code, so I assumed I’d refactored something incorrectly in one of the new Storyboards, perhaps by using a “show” segue where I should have used a “show detail” one. However everything checked out on that front.
I then did what I usually do when I can’t understand exactly why an app is doing something, and started a fresh iOS project to attempt to replicate the behaviour. In this case I found that the same sequence of screens as in our app didn’t trigger the same outcome with vanilla iOS code. This meant there was unlikely to be a bug in iOS and so I took a closer look at our app.
After several hours of debugging and at my wits’ end, I eventually tried deleting the Storyboard that contained the “push detail” segue (which is responsible for putting a note on the screen) and rebuilt it from scratch – and found that the issue no longer occurred. I was sure that functionally this Storyboard was identical to the last, so I reverted my change and went through the original Storyboard again, piece by piece.
Eventually I tried changing the type of the problematic segue to “push”, then back to “push detail” – and noticed that Xcode had flagged the file as modified. This was odd because my operation could be considered a zero sum change. Doing a git diff revealed the following delta in the underlying XML (used by Apple to represent Storyboards under the hood):
– <segue destination=”01I-yK-YKh” kind=”showDetail” identifier=”ShowNote” id=”WT4-Vi-lh3″>
– <nil key=”action”/>
+ <segue destination=”01I-yK-YKh” kind=”showDetail” identifier=”ShowNote” id=”WT4-Vi-lh3″/>
In other words, a <nil key=”action”/> element had been causing the odd behaviour we were seeing.
I’ve no idea what that element is (though I’m fairly sure we hadn’t put it there deliberately), but it illustrates a danger of relying on an abstraction to manage the application UI. Interface Builder has its merits such as allowing designers to get involved with crafting an app, and letting new developers find their way around a project much more easily, but like any abstraction it can “leak”, and lead to unexpected side effects that cause frustration and puzzlement.