TN3154: Adopting SwiftUI navigation split view
Use navigation split view to enable two and three column navigation in your SwiftUI app while maintaining compatibility with earlier OS versions.
Overview
NavigationSplitView is a view that presents views in two or three columns, where selections in leading columns control presentations in subsequent columns. The Navigation split view API is available on iOS 16, macOS 13, tvOS 16, watchOS 9 and visionOS 1.
Transition from the deprecated NavigationView API if your app has a minimum deployment target of at least iOS 16, macOS 13, tvOS 16, watchOS 9 or visionOS 1. For more information, see Migrating to new navigation types.
This document describes how using a custom wrapper makes it easier to adopt NavigationSplitView and ensures your app remains compatible with the deprecated NavigationView, without increasing the app deployment target.
Using API availability check to provide backward compatibility using a custom wrapper
Use the #available() keyword to execute code conditionally based on required platform and version. This allows your app use NavigationSplitView if the specified OS versions are iOS 16, macOS 13, tvOS 16, watchOS 9 or visionOS 1 while supporting NavigationView for earlier OS versions.
To ensure backward compatibility on earlier versions of iOS, macOS, tvOS and watchOS, create and use a custom wrapper view that conditionally uses either NavigationSplitView or NavigationView depending on the availability of the API. For apps that use one column navigation view, consider using NavigationStack.
struct NavigationSplitViewWrapper<Sidebar, Content, Detail>: View where Sidebar: View, Content: View, Detail: View {
private var sidebar: Sidebar
private var content: Content
private var detail: Detail
init(
@ViewBuilder sidebar: () -> Sidebar,
@ViewBuilder content: () -> Content,
@ViewBuilder detail: () -> Detail
) {
self.sidebar = sidebar()
self.content = content()
self.detail = detail()
}
var body: some View {
if #available(iOS 16, macOS 13, tvOS 16, watchOS 9, visionOS 1, *) {
// Use the latest API available
NavigationSplitView {
sidebar
} content: {
content
} detail: {
detail
}
} else {
// Alternative code for earlier versions of OS.
NavigationView {
// The first column is the sidebar.
sidebar
// Initial content of the second column.
content
// Initial content for the third column.
detail
}
.navigationViewStyle(.columns)
}
}
}Revision History
2023-08-29 First published.
See Also
Latest
TN3205: Low-latency communication with RDMA over ThunderboltTN3206: Updating Apple Pay certificatesTN3179: Understanding local network privacyTN3190: USB audio device design considerationsTN3194: Handling account deletions and revoking tokens for Sign in with AppleTN3193: Managing the on-device foundation model’s context windowTN3115: Bluetooth State Restoration app relaunch rulesTN3192: Migrating your iPad app from the deprecated UIRequiresFullScreen keyTN3151: Choosing the right networking APITN3111: iOS Wi-Fi API overviewTN3191: IMAP extensions supported by Mail for iOS, iPadOS, and visionOSTN3134: Network Extension provider deploymentTN3189: Managing Mail background traffic loadTN3187: Migrating to the UIKit scene-based life cycleTN3188: Troubleshooting In-App Purchases availability in the App Store