iOS
More About Split View Controllers in iOS 14
Matt Neuburg
Written on February 18, 2021

In an earlier article, I talked about how split view controllers (UISplitViewController) have been completely revamped in iOS 14. In particular, they “adapt” to the environment’s horizontal size class in a whole new way. A two-part split view has three “columns”, but they are not all displayed at the same time:
-
The
.primary
and.secondary
columns, typically the master and detail view controllers, are displayed for a.regular
horizontal size class, such as an iPad. -
The
.compact
column, which can be any sort of view controller you like, is displayed for a.compact
horizontal size class, such as an iPhone.
This architecture is nice and simple; the trick, as I explained in the earlier article, is what to do so as not to lose the user’s place within the app when the environment toggles between the .regular
and .compact
size class.
Now I want to summarize more of the general changes in how split view controllers work in iOS 14.
The Three-Column Trick
The most obvious change in the split view controller interface is that a split view controller can now have three columns simultaneously. This is totally new in iOS 14 and is evident the moment you start to use iOS 14 on an iPad. An excellent case in point is the Mail app.
In iOS 13, the Mail app is a split view where the master view controller is itself a navigation controller that actually navigates internally. Within this navigation controller, the root view controller lists mailboxes, and you tap one to see a list of messages in that mailbox — still in the master view controller. Then you can tap a message listing to read the actual message in the detail view controller.
But in iOS 14, the list of mailboxes and the list of messages in the selected mailbox are two different columns — the .primary
column and the .supplementary
column.
This sounds confusing, and I suppose in a way it is, but it will seem a lot more coherent when you know the following simple rule: in a three-column split view controller layout, the user might be able to see the .supplementary
column without seeing the .primary
column, but it is impossible to see the .primary
column without also seeing the .supplementary
column. So the .supplementary
column, despite its name, is the important one; it’s the one that determines “where we are” in the detail view controller (the .secondary
column).
Whether your split view controller will have two columns or three columns is something you must decide when you initialize the split view controller. The initializer is init(style:)
, and the style
is either .doubleColumn
or .tripleColumn
. (A third option, .unspecified
, actually means: “Revert to the split view controller architecture from iOS 13 and before.”) Trying to assign something to the split view controller’s .supplementary
column in a .doubleColumn
layout is illegal and will cause your app to crash.
Display Modes
In the above screenshot of the Mail app, look at how the three columns are laid out. There’s the .primary
column at the left (mailboxes), followed by the .supplementary
column to its right (mail messages). To the right of that, darkened and shoved partway off the screen, is the .secondary
column displaying the content of the selected message.
That layout, and every possible layout, is a display mode. For example, the user who is looking at the Mail app in that screenshot can now slide the .supplementary
column to the left, shoving the .primary
column entirely off the screen. Now we have the familiar splitscreen layout with the list of messages on the left and the selected message on the right. That’s simply a different display mode.
You can manipulate the display mode in code. To learn the actual display mode being used, ask for the split view controller’s current displayMode
. To alter the display mode, set the preferredDisplayMode
property; use .automatic
to allow the display mode to adopt its default value.
Possible values are:
-
.secondaryOnly
: Just the.secondary
column is visible, occupying the entire interface. -
.oneBesideSecondary
,.oneOverSecondary
: There are two columns, either side by side (beside
) or with the.secondary
column fullscreen and with theone
as an overlay (over
). The name is coy about which column is theone
because this will be different depending on whether there are two columns or three columns!-
If this is a double-column layout, the
one
is the.primary
column. -
If this is a triple-column layout, the
one
is the.supplementary
column.
-
-
.twoBesideSecondary
,.twoOverSecondary
,.twoDisplaceSecondary
: Applicable only in a three-column layout.two
means both the.primary
and.supplementary
columns appear; the difference is in how the.secondary
column appears in relation to them: -
beside
: All three columns are side by side. -
over
: The.primary
and.supplementary
columns constitute an overlay. -
displace
: The.secondary
column is beside the other two, but without being reduced in width — instead, it is darkened, as in an overlay mode, and pushed partway offscreen (as in the screenshot above).
Your preferred display mode is only a preference; the runtime remembers and applies it as appropriate in terms of the interface’s orientation and the user’s actions. If the goal is to change the display mode on just one occasion, you might be better off calling show(_:)
or hide(_:)
, which take a column as their parameter.
Split Personality
My list of display modes didn’t quite tell the whole story, because it turns out that the split view controller’s response to your preferredDisplayMode
setting is also mediated by its split behavior. This is a rule limiting what display modes are permitted.
To learn the actual split behavior in effect, ask for the split view controller’s current splitBehavior
. To alter the split behavior, set the preferredSplitBehavior
property; use .automatic
to allow the split behavior to adopt its default value.
Possible values are:
tile
: Noover
ordisplace
display mode is allowed.overlay
: Nobeside
ordisplace
display mode is allowed.displace
: Noover
display mode is allowed;.twoBesideSecondary
is not allowed, but.oneBesideSecondary
is allowed, as otherwise we’d never see the.primary
column in a double-column layout!
The point of the split behavior is that if you ask for a display mode that isn’t permitted by the split behavior, you’ll get a different display mode. For instance, if you ask for .oneBesideSecondary
when the split behavior is .overlay
, you’ll get .oneOverSecondary
.
Buttons and Gestures
So far, I’ve been talking from the point of view of you, the programmer. Now I want to say something about the affordances that enable the user to alter the display mode. The user’s ability to switch between display modes using buttons and gestures is affected by two properties:
-
presentsWithGesture
: The default istrue
. Despite the name, it actually affects two things:-
The enablement of the swipe gesture that summons the
.primary
column. -
The presence of the button that does the same thing.
Perhaps the easiest way to understand the implications of
presentsWithGesture
is to think about what happens if you set this property tofalse
: the user then cannot hide the.primary
column if it is showing in abeside
display mode, and cannot summon the.primary
column at all if it is not showing; giving the user a way to do those things, if desired, would then be up to you. -
-
showsSecondaryOnlyButton
: The default isfalse
. Iftrue
, then in a three-column layout, a button is present that allows the user to dismiss all columns except the.secondary
column, or to summon the.supplementary
column if it is not showing.A good place to see this feature honored in the breach is in the same Mail screenshot I already showed. From that situation, the user can tap on the right side of the screen to reduce things to a side by side layout with the
.supplementary
view on the left and the.secondary
view on the right; but the user cannot dismiss the.supplementary
view entirely because there’s no button for that. (But the user can rotate the iPad to portrait mode, where the.supplementary
view is an overlay, and now it is possible to dismiss the.supplementary
column.)
Other Tweaks
Here are some further settings that let you customize the size and position of the pieces in the split view controller’s layout:
-
primaryEdge
:
Which side the.primary
column (and.supplementary
column) appears on. Your choices are.leading
and.trailing
. A.trailing
split view controller is a rarity, but clearly, it isn’t illegal. -
preferredPrimaryColumnWidth
,preferredPrimaryColumnWidthFraction
minimumPrimaryColumnWidth
,maximumPrimaryColumnWidth
preferredSupplementaryColumnWidth
,preferredSupplementaryColumnWidthFraction
minimumSupplementaryColumnWidth
,maximumSupplementaryColumnWidth
:
Sets the widths that the.primary
and.supplementary
columns will have when showing.
Using the width
properties is a little tricky. Here are some tips:
-
To specify the default width, use
UISplitViewController.automaticDimension
. -
To let the
.supplementary
column fill the remainder of the screen, useUISplitViewController.automaticSupplementaryFillDimension
. -
To learn the actual width being used, ask for the current
primaryColumnWidth
andsupplementaryColumnWidth
. -
If you set both a fractional and an absolute width, the absolute width takes precedence.
-
And here’s the one that always mystifies me: You must set the preferred maximum width before any other width setting will take effect!
It’s All Good
If all of that seems confusing, the thing to keep in mind is that in general, the default settings are just great. The split view controller, right out of the box, has the “right” behaviors, the “right” gestures and buttons, the “right” display modes in all the various possible situations (different device types and orientations). You wouldn’t get into modifying those defaults unless you had a special purpose, and in that case, you’d explore things more deeply.
There’s a little more to know about split view controllers; in particular, don’t forget to investigate the delegate protocol, which gives you a lot of information about what the user is up to. But really, what I’ve said in this article and the previous one pretty much constitutes the whole of the story. In general, what I like about split view controllers in their new iOS 14 incarnation is that they are simple. That should make them more usable, from a programmer’s point of view, than ever before.
If you missed part 1, check it out here.