iOS 14 UISplitViewController: 5 Issues That You May Run Into

Rostyslav Dovhaliuk
The Startup
Published in
5 min readSep 3, 2020

--

The final build of iOS 14.0 will be released soon, and it’s about time to make sure our apps are running great on iOS 14. This year Apple introduced major changes in UISplitViewController, which are mostly dedicated to a new three-column layout and a sidebar. While the new sidebar UI looks great, in this post I will only focus on changes to existing functionality that we already use in our apps and show what can go wrong when your existing app is run on iOS 14. With that said let’s dive in.

New style property and why there is an unspecified style type

Probably the first thing that you’ll notice when looking at the UISplitViewController API exclusive to iOS 14 will be a new initializer that accepts UISplitViewController.Style as a single argument. While doubleColumn and tripleColumn styles are fairly self-explanatory, there is a third mysterious option called unspecified. After some testing, it became clear that unspecified style is a way to tell UIKit that you want iOS 13 behavior, so if you don’t want to deal right now with all the issues described next, you can enjoy the old behavior even when running on iOS 14, if you’ll use the unspecified style. The only issue with this scenario is that it is a bit tricky to set this specific style. Next, I’ll quickly summarize solutions that do and don’t work for such a task.

What does not work

  1. Calling new initializer with unspecified style. The most obvious approach, however, it triggers runtime exception with a message

API misuse. -initWithStyle: may not be used with UISplitViewControllerStyleUnspecified.

2. Performing setStyle: selector. Leads to exception too with a message

SPI misuse. -setStyle: should be used by IB to set up UISplitViewController for column-style behavior using UISplitViewControllerStyleDoubleColumn or -TripleColumn (yep, there is a typo in that message).

What does work

  1. If you instantiate your UISplitViewController in code, just call the default NSObject initializer: UISplitViewController().
  2. Thankfully, there is also a solution for those who instantiate their UISplitViewController from the storyboard. In the 5th beta of Xcode 12, Apple allowed us to set the unspecified style directly from the Interface Builder.

Want to use the modern API instead? Great, stay tuned to see what breaks as soon as you’ll pick the doubleColumn style.

Clipped master view controller’s view

After choosing the doubleColumn style in Interface Builder and running my app I noticed that for some reason the whole master view controller was clipped.

The layout of the main menu view controller was created years ago when Safe Area layout guides were not present. Hence, the collection view was constrained to its superview, instead of Safe Area, which caused this weird clipping.

After enabling Safe Area layout guides in File inspector everything went back to normal.

As Geoff Hackworth explained in his Tweet the primary view controller is wider than its visible area to support the edge swipe when the primary view controller is hidden. Make sure you have “Show Device Bezel” enabled in Simulator to perform the edge swipe in it.

DisplayModeButtonItem is no longer accessible

After navigating a bit through the app I noticed the following message in the console

[Assert] displayModeButtonItem is internally managed and not exposed for DoubleColumn style. Returning an empty, disconnected UIBarButtonItem to fulfill the non-null contract.

This message showed up right after I tried to set leftBarButtonItem of a detail view controller, which was about to be presented:

Previously this solution allowed me to show a button at the detail view controller that could expand the view controller to the full width of an iPad.

However, on iOS 14 similar functionality is provided by default with a new button displayed on top of master and detail view controllers, so the legacy solution should be executed only on older iOS versions.

Tint color of expand & collapse button during the transition

If you look closely at the last gif, you’ll probably notice that the color of the button changes to standard iOS blue while the transition is going on while UINavigationBar.appearance().tintColor is used at other times. After inspecting the view hierarchy it turned out that there are 3 of such buttons.

Most likely one of them is shown only when the transition is in progress. After trying several approaches I figured out that the color of that button is defined by UISplitViewController’s view tint color.

Nonworking delegate callback

After fixing previous flaws I decided to see if everything is good when the app is run on an iPhone. Unfortunately, after launching the app I saw the placeholder view controller instead of the main menu and a message in the console saying

[UISplitViewController] Skipping delegate callback, splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:. Unsupported for UISplitViewController style DoubleColumn

Thankfully, there is a new callback introduced in iOS 14, which we can use for the very same purpose:

Still, the warning about skipped delegate callback will be printed in your console (assuming that you’ve kept the previous callback to support the pre-iOS 14 systems).

Final thoughts

Overall I’m glad that this year’s migration to the latest iOS turned out to be not complicated at all. Hope you’ll update your apps without issues as well. If you enjoyed this post, please check out my app in the AppStore. That’s all, and thanks for reading!

--

--