SwiftUI

A Beginner’s Guide to NavigationSplitView in SwiftUI for iOS 16


In iOS 16, other than introducing the new NavigationStack, Apple also released a new view container named NavigationSplitView for developers to create two or three column navigation interface. If you want to build UI similar to the stock Mail app, you should check out this split view component.

While NavigationSplitView is more suitable for iPadOS and macOS apps, you can also use it on apps for iPhone. The view component automatically adapts itself for iPhone. Instead of displaying a multi-column interface, it creates a single-column experience.

The new NavigationSplitView comes with various options for you to customize its appearance and operations. You can change the column width and programmatically show/hide the columns.

In this tutorial, we will create a three-column navigation UI using NavigationSplitView.

Let’s get started.

The Basic Usage of NavigationSplitView

The NavigationSplitView supports both two-column and three-column navigation experience. Their implementations are quite similar. To create a two-column navigation UI, you write the code like this:

For 3-column navigation interface, you add the content parameter in between:

We will start with the two-column navigation UI and eventually build the three-column design.

Building the 2-Column Navigation Interface

If you’ve read my previous tutorial on the expandable list view, you may know that I’m a big fan of La Marzocco. In that tutorial, I showed you how to create an expandable list view with inset group style.

Now let’s turn this expandable list into a two level navigation interface like the screenshot shown below:

swiftui-navigationsplitview-two-column

Before we create the split view, let’s begin with the data model. We create a struct to model a menu item:

To make a nested list, the key here is to include a property that contains an optional array of children (i.e. subMenuItems). Note that the children are of the same type of its parent.

For the top level menu items, we can create an array of MenuItem like this:

For each of the menu item, we specify the array of the sub-menu items. In case if there is no sub-menu item, you can omit the subMenuItems parameter or pass it a nil value. For the sub-menu items, we can define them like this:

To better organize the data model, we create a struct called CoffeeEquipmentModel like this:

The mainMenuItems array holds the sample menu items. Both subMenuItems and menuItem are helper methods for looking up a specific category or menu item.

Now that we’ve prepared the data model, let’s move onto the implementation of the navigation split view. Create a new file named TwoColumnSplitView.swift using the SwiftUI view template. Update the TwoColumnSplitView struct like this:

The first closure of NavigationSplitView presents the main menu item. We use a List view to loop through all mainMenuItems in the data model and display each of the menu items using a HStack view.

We also have a state variable named selectedCategoryId, which is used to hold the selected main menu item.

For the detail closure, this is where the submenu item is rendered. If a category is selected, we call the subMenuItems method to get the submenu items for that particular category. We then display the submenu items using List view. Conversely, if no category is selected, we display a text message instructing the user to choose a category.

Once you made the changes, you should see a two-column navigation UI in the Xcode preview.

swiftui-split-view-three-columns

Creating a Three-Column Navigation Interface

Now that we’ve created a two-column navigation interface, let’s further enhance it to provide users with a three-column navigation experience. The extra column is used for displaying the photo of the selected equipment.

swiftui-navigation-split-view-three-column-demo

To convert the two-column navigation interface to three-column, we need to implement an additional parameter (i.e. content) for the NavigationSplitView. Let’s create a new view named ThreeColumnSplitView like this:

Basically, the code in the content closure should be very similar to you. The content parameter is designed for displaying the submenu items. Thus, we use the List view to show the submenu items for the selected category.

When an item is selected in the submenu, the app shows the equipment photo. This is achieved by the code written in the detail closure.

After the code changes, the preview pane should show you a two-column layout.

swiftui-navigation-empty

By default, the first column is hidden. You need to tap the menu button at the top-left corner to reveal it.

To control the visibility of the split view, you can declare a state variable of the type NavigationSplitViewVisibility and set its value to .all:

When instantiating the NavigationSplitView, it has an option parameter named columnVisibility. You can simply pass the binding of columnVisibility to control the visibility of the columns.

swiftui-column-visiblity-split-view

The NavigationSplitViewVisibility.all value tells iPadOS to display all the three columns. There are other options including:

  • .automatic – Use the default leading column visibility for the current device. This is the default setting.
  • .doubleColumn – Show the content column and detail area of a three-column navigation split view.
  • .detailOnly – Hide the leading two columns of a three-column split view. In other words, only the detail area shows.

Customizing the Style of Navigation Split Views

Have you tested the app in iPad Portrait? By default, the detail area takes up the whole screen when the iPad device is in portrait mode. So, when you bring up the main menu and submenu areas, the detail area is hidden behind these two leading columns.

swiftui-portrait-multiple-column

If you don’t like this style, you can change it by attaching the .navigationSplitViewStyle modifier to NavigationSplitView:

The default value is set to .automatic. If you set the value to .balanced, it reduces the detail area such that the two leading columns can appear at the same time.

swiftui-splitview-multi-column-balanced

What’s Next

This tutorial gives you an introduction to NavigationSplitView in iOS 16. It’s very easy to create multi-column navigation experience for iPad users. Even if you develop apps for iPhone users, NavigationSplitView can adapt itself to fit the navigation experience on narrower screens. For example, when iPhone 13 Pro Max is in portrait mode, the split view shows a one-column navigation. If you rotate the device sideway, the split view changes to a multi-column layout.

Therefore, take some time to study this split view component and apply it to your app whenever this kind of UI makes sense.

For reference, if you want to learn more about NavigationSplitView, you can check out this WWDC video.

If you enjoy this article and want to dive deeper into SwiftUI, you may check out our Mastering SwiftUI book.

Tutorial
SpriteKit Introduction Part 1: Scenes, Nodes, Labels and Points
iOS
Introduction to iOS 8 App Extension: Creating a Today Widget
macOS
Deploying Mac Apps Outside App Store: How to Remember User Intent for Folders
Shares