Class

UISplitViewController

The UISplitViewController class is a container view controller that presents a master-detail interface. In a master-detail interface, changes in the primary view controller (the master) drive changes in a secondary view controller (the detail). The two view controllers can be arranged so that they are side-by-side, so that only one at a time is visible, or so that one only partially hides the other. In iOS 8 and later, you can use the UISplitViewController class on all iOS devices; in previous versions of iOS, the class is available only on iPad.

Overview

When building your app’s user interface, the split view controller is typically the root view controller of your app’s window. The split view controller has no significant appearance of its own. Most of its appearance is defined by the child view controllers you install. You can configure the child view controllers using Interface Builder or programmatically by assigning the view controllers to the viewControllers property. The child view controllers can be custom view controllers or other container view controller, such as navigation controllers.

The split view controller determines the arrangement of its child view controllers based on the available space. In a horizontally regular environment, the split view controller presents its view controllers side-by-side whenever possible. In a horizontally compact environment, the split view controller acts more like a navigation controller, displaying the primary view controller initially and pushing or popping the secondary view controller as needed. You can also ask the split view controller to prefer a specific arrangement by assigning a value to the preferredDisplayMode property.

When displayed onscreen, the split view controller works with its Delegation object to manage the presentation of its child view controllers. The delegate is an object you provide that adopts the UISplitViewControllerDelegate protocol. Use the methods of that protocol to customize the behavior of your split view interface when changes occur. For more information about the protocol methods, see UISplitViewControllerDelegate.

Configuring the Appearance of the Split View Interface

The visual configuration of a split view controller is controlled by its current display mode. You do not set the display mode directly; instead, you set it indirectly using the preferredDisplayMode property. The split view controller makes every effort to respect the display mode you specify but may not be able to accommodate that mode visually because of space constraints. For example, the split view controller cannot display its child view controllers side-by-side in a horizontally compact environment.

Table 1 lists the available display modes and describes how the view controllers are arranged onscreen. The table also lists the constants you use to request the specified display mode.

Table 1

Display modes for a split view controller

Mode

Description

Side-by-side

Both view controllers are displayed onscreen at the same time. The primary view controller is displayed on the left side and is typically narrower than the secondary view controller. You can adjust the primary view controller’s width using the preferredPrimaryColumnWidthFraction property.

This display mode is not applied when the isCollapsed property is true. In a collapsed interface, only one view controller at a time is visible.

This mode is represented by the allVisible constant.

Hidden

The secondary view controller is displayed onscreen and the primary view controller is off screen.

To display the primary view controller, you must present it modally or change the display mode.

This mode is represented by the primaryHidden constant.

Overlay

The secondary view controller is onscreen and the primary view controller is layered on top of it. In this mode, the primary view controller partially obscures the secondary view controller.

This mode is represented by the primaryOverlay constant.

After setting the preferred display mode, the split view controller updates itself and reflects the actual display mode in the displayMode property. You can change the preferred display mode at any time, and doing so causes the split view controller to adjust itself accordingly. The split view controller also installs a built-in gesture recognizer that lets the user change the display mode using a swipe. You can suppress this gesture recognizer by setting the presentsWithGesture property to false.

The displayModeButtonItem method returns a special bar button item for changing the display mode that you can incorporate into your app’s user interface. The split view controller manages the behavior and appearance of this item. All you have to do is add it to an appropriate navigation bar or toolbar in your interface. When tapped, the button sends an action to the split view controller telling it to change its current display mode to the one specified by the targetDisplayModeForAction(in:) method of the split view controller’s delegate. Specifying a display mode of automatic (or not implementing the delegate method at all) causes the split view controller to implement behavior that is appropriate for the current size class. For example, on an iPad in portrait orientation, the split view controller toggles between the hidden and overlay modes. Gesture-based actions also use the delegate method to determine which display mode to employ.

Changing Child View Controllers in a Split View Interface

When designing your split view interface, it is best to install primary and secondary view controllers that do not change. A common technique is to install navigation controllers in both positions and then push and pop new content as needed. Having these types of anchor view controllers makes it easier to focus on your content and let the split view controller apply its default behavior to the overall interface.

In cases where you do need to change either the primary or secondary view controller, it is recommended that you do so using the show(_:sender:) and showDetailViewController(_:sender:) methods. Using these methods (instead of modifying the viewControllers property directly) lets the split view controller present the specified view controller in a way that is most appropriate for the current display mode and size class. The split view controller knows how to adjust the interface in more intuitive ways. It even works with other container view controllers (like navigation controllers) to present view controllers. For example, in a compact environment where the primary view controller is a navigation controller, calling showDetailViewController(_:sender:) does not replace the secondary view controller. Instead, the primary navigation controller pushes the view controller onto its navigation stack.

Collapsing and Expanding the Split View Interface

The split view controller performs collapse and expand transitions when its size class toggles between horizontally regular and horizontally compact. During these transitions, the split view controller changes how it displays its child view controllers. When changing from horizontally regular to horizontally compact, the split view controller collapses one view controller onto the other. When changing from horizontally compact back to horizontally regular, it expands the interface again and displays one or both of its child view controllers depending on the display mode.

When transitioning to a collapsed interface, the split view controller works with its delegate to manage the transition. At the end of a collapse transition, the split view controller normally shows only the content from its primary view controller. You can change this behavior by implementing the primaryViewController(forCollapsing:) method in your split view controller delegate. You might use that method to specify the secondary view controller or an entirely different view controller—perhaps one better suited for display in a horizontally compact environment. If you want to perform any additional adjustments of the view controllers and view hierarchy, you can also implement the splitViewController(_:collapseSecondary:onto:) method in your delegate.

The expansion process reverses the collapsing process by asking the delegate to designate which view controller becomes the primary view controller and to give the delegate a chance to perform the transition itself. If you implement the delegate methods for collapsing your split view interface, you should also implement the primaryViewController(forExpanding:) and splitViewController(_:separateSecondaryFrom:) methods for expanding that interface. If you do not implement any of the methods, the split view controller provides default behavior to handle the collapsing and expanding transitions.

For more information about the methods you use to manage the collapse and expand transitions, see UISplitViewControllerDelegate.

Message Forwarding to Its Child View Controllers

A split view controller interposes itself between the application’s window and its child view controllers. As a result, all messages to the child view controllers must flow through the split view controller. This works generally as you might expect and the flow of messages should be relatively intuitive. For example, view appearance and disappearance messages are sent only when the corresponding child view controller actually appears on screen.

State Preservation

In iOS 6 and later, if you assign a value to this split view controller’s restorationIdentifier property, it preserves any child view controllers that have their own valid restoration identifier. During the next launch cycle, the split view controller restores the preserved view controllers to their previous state. The child view controllers of a split view controller may use the same restoration identifiers. The split view controller automatically stores additional information to ensure that each child’s restoration path is unique.

For more information about how state preservation and restoration works, see App Programming Guide for iOS.

Symbols

Managing the Child View Controllers

var viewControllers: [UIViewController]

The array of view controllers managed by the receiver.

var presentsWithGesture: Bool

Specifies whether a hidden view controller can be presented and dismissed using a swipe gesture.

Managing the Display Mode

var preferredDisplayMode: UISplitViewControllerDisplayMode

The preferred arrangement of the split view controller interface.

var displayMode: UISplitViewControllerDisplayMode

The current arrangement of the split view controller’s contents.

var displayModeButtonItem: UIBarButtonItem

A button that changes the display mode of the split view controller.

Getting the Split View Configuration

var isCollapsed: Bool

A Boolean value indicating whether only one of the child view controllers is displayed.

var preferredPrimaryColumnWidthFraction: CGFloat

The relative width of the primary view controller’s content.

var primaryColumnWidth: CGFloat

The width (in points) of the primary view controller’s content.

var minimumPrimaryColumnWidth: CGFloat

The minimum width (in points) required for the primary view controller’s content.

var maximumPrimaryColumnWidth: CGFloat

The maximum width (in points) allowed for the primary view controller’s content.

Accessing the Delegate Object

var delegate: UISplitViewControllerDelegate?

The delegate you want to receive split view controller messages.

Action Methods for Displaying View Controllers

func showDetailViewController(UIViewController, sender: Any?)

Presents the specified view controller as the secondary view controller of the split view interface.

func show(UIViewController, sender: Any?)

Presents the specified view controller as the primary view controller in the split view interface.

Constants

UISplitViewControllerDisplayMode

Constants describing the possible display modes for a split view controller.

Split View Controller Dimensions

Constant indicating the default width for the primary view controller.