SwiftUI SplitView Compact Column Control

In iOS 17, Apple added control over which column shows when a Split View collapses to a single column.

Apple added NavigationSplitView to SwiftUI in iOS 16 for creating two or three column layouts. The Split View configuration available in iOS 16 includes controls for column visibility, width, and style. It was missing API for controlling which column the split view shows when collapsing to a single column for compact widths. Apple fixed that gap in iOS 17 (and macOS 14).

Preferred Compact Column

When a split view collapses to a single column the default behaviour is for SwiftUI to automatically choose which view to show on top based on the content of the columns. On an iPhone that seems to mean showing the sidebar view but that’s not always what I want.

There are new initialisers in iOS 17 for creating two or three column split views. In both cases you can pass a binding to a NavigationSplitViewColumn state that controls which column shows on top when the split view collapses.

Here’s the three column version where I’ve set the initial state to show the content view when collapsed:

struct ContentView: View {
  @State private var compactColumn = NavigationSplitViewColumn.content

  var body: some View {
    NavigationSplitView(preferredCompactColumn: $compactColumn) {
      Sidebar(compactColumn: $compactColumn)
    } content: {
      Content(compactColumn: $compactColumn)
    } detail: {
      Detail(compactColumn: $compactColumn)
    }
  }
}

The NavigationSplitViewColumn type has three possible values for the sidebar, content, and detail columns. Changing the compact column state causes the split view to switch to showing that column when collapsed.

For example, to allow my detail view to programmatically pop back to the sidebar column:

struct Detail: View {
  @Binding var compactColumn: NavigationSplitViewColumn
    
  var body: some View {
    Button("Sidebar") {
      compactColumn = .sidebar
    }
    .navigationTitle("Detail")
  }
}

Changing the preferred compact column has no visible effect when the split view is not collapsed though it will change what happens the next time the split view collapses.