Creating a Master-Detail Interface in SwiftUI

Master-detail interfaces are common in iOS and Mac apps. Select an item from the master view to see additional information in the detail view. In SwiftUI you use two views to create a master-detail interface: NavigationView and NavigationLink.

UPDATE

Apple deprecated NavigationView in iOS 16 and macOS 13. The replacements for NavigationView are NavigationStack and NavigationSplitView, but they require iOS 16+ and macOS 13+. If you want to support earlier OS versions, you must use NavigationView.

A navigation view is the most common way to create a master-detail interface in SwiftUI. On iOS selecting an item from the master view, which is usually a SwiftUI list, takes you to the detail view. On macOS selecting an item from the master view shows the details in the detail view.

The following code shows how to create a navigation view:

var body: some View {
  NavigationView {
    MasterView()
    DetailView()
  }
}

In a real app you will pass data as arguments to the master view and detail view. The data depends on your app, which is why I didn’t supply any arguments in the code listing.

The article Passing Data to SwiftUI Views provides more detailed information on passing data to views.

The final part of creating a master-detail interface is to add a navigation link in the master view and set its destination to the detail view.

List(items) { item in
  NavigationLink(destination: DetailView()) {
    Text(item.title)
  }
}

This example creates a navigation link for each item in the list. Selecting an item from the list fills the detail view with information about the selected item. In a real app you will pass the data to show in the detail view as an argument to the detail view.

Handling Selection

There are some situations where you may need to hold on to the selection. Mac apps need access to the selected item when deleting an item from a list.

In the master view create a property to store the selection. Make it optional and set its value to nil.

@State private var selectedItem: Item? = nil

When someone selects an item from the list, the selectedItem property will store it. In the call to create the navigation link, add the tag and selection arguments. The tag is usually the current item. The selection is the selected item.

List(items) { item in
  NavigationLink(destination: DetailView(),
                tag: item,
              	selection: $selectedItem) {
    Text(page.title)
  }
}

Sample Project

I put a sample project on master-detail interfaces on GitHub. It builds upon the project from the Make a Markdown Editor in SwiftUI article by displaying a list of Markdown pages to edit. Look at the files ContentView.swift and PageListView.swift for the code on making the master-detail interface.

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.