Fighting With UISplitViewController
January 31, 2020

Bookish Development Diary, episode 6.

Call me an idiot (“Sam, you’re an idiot” - ed.), but whenever I try to use UISplitViewController, I seem to get myself into a tangle. It doesn’t work the way I expect it to.

What I generally want is an index view side-by-side with a stack of detail views.

A Simple Index With Detail

If I’m on a phone, or a horizontally-compact environment, I want the index to collapse onto the stack, so that there’s just one view. Tapping an index item here should push the detail view onto the stack, replacing the index.

Show Index By Default When Collapsed

Assuming that I’m not restoring the previous state of the app, this is how things should start in a compact environment. I definitely don’t want the app to start showing an empty detail view, and hiding the index 🤦🏼‍.

If the view is collapsed and some detail is showing, I don’t want to be able to pop up the index view, or slide it over the detail.

I just want to be able to pop the navigation stack to get back to the index.

Pop To Get Back To The Index

This is not rocket science!

I’m sure that you can get UISplitViewController to behave like this, but invariably I seem to end up having to jump through a lot of hoops to do it, and even then sometimes do it wrong.

I hit this situation yet again whilst working on an example viewer app for Datastore, so I started wondering how easy it would be to just throw it away and make something simpler…


If you keep the spec simple, it turns out not to be too difficult, and you can find my attempt here.

I called it IndexDetailViewController as my use case is specifically for indexes. I guess it could be called MasterDetailViewController instead.

The way I approached this problem is to use a UIStackView controller to manage the side-by-side behaviour.

This already conveniently supports animation if you hide one of the arranged views, which is handy.

Rather than expecting you to supply a navigation controller for the detail (as UISplitViewController does), my IndexDetailViewController makes one for you and manages it internally.

When the controller is collapsed, it removes the index from its UIStackView, and adds it to the relevant place in the detail navigation stack.

That’s pretty much all there is to it. Not bad for a few hours of hacking.

If you want to see it in action, the repo includes a simple example.

No doubt there’s lots of subtle extra behaviour that UISplitViewController gives you, and which I’m missing.

It doesn’t add its own chrome, and I haven’t added the bits & bobs necessary to allow you to configure it completely in Interface Builder.

I could add all of this relatively easily, but I like the simplicity of what I have, and for now, IndexDetailViewController serves my purposes.

Maybe I’ll slowly add the missing stuff.

Maybe one day I’ll end up re-implementing it using UISplitViewController under the hood! Time will tell… but either way, IndexDetailViewController is a good abstraction for the behaviour I actually want.

« XPkg - A Package Manager For Machine Configuration Catalyst+SwiftUI+Sparkle=? »
Got a comment on this post? Let us know at @elegantchaoscom.