NavigationStack in SwiftUI
Navigation has always been a crucial part of SwiftUI. As apps become more complex, however, linear navigation can become difficult to manage. At WWDC22, Apple introduced a new navigation API designed to make complex, data-driven flows easier to build.
In this tutorial, we’ll use a small list-based app to implement NavigationStack and show why it gives you more control than the older NavigationView approach.
NavigationView and the older approach
Before NavigationStack, you would typically create a navigation interface using NavigationView and NavigationLink. That works very well for simple, linear navigation.
It becomes harder when a user is several screens deep in a flow, or when a deep link needs to take the user directly to a specific destination. For example, if your flow is A → B → C → D → E, returning to the beginning or rebuilding the stack at C can require workarounds.
Download the original sample project and open DashboardContentView to follow along.
Replace NavigationView with NavigationStack
Replace the NavigationView on line 17 with NavigationStack(path: $viewModel.navigationStack). Don’t worry about the error messages that appear yet; we’ll address them in the next step.
Master NavigationStack’s path
If NavigationStack and NavigationPath feel confusing at first, think of the path as the data that represents what is currently inside the navigation stack.
On line 17 you now reference viewModel.navigationStack, so declare it in ListViewModel. Add @Published var navigationStack: [ListItemModel] = [ListItemModel]() below your existing @Published var appsData... property.
Once the property is added, the error from step 1 should disappear. The array starts empty and will represent the items in the NavigationStack as the user navigates.
Configure .navigationDestination()
To fully take advantage of NavigationStack, make two small changes: add .navigationDestination() and update the NavigationLink initializer.
The important change is the destination configuration, which lets you choose the destination view based on the value placed into the navigation stack. The NavigationLink is also updated so that it supplies the relevant ListItemModel.
Explore complete iOS app projects
After you understand path-based navigation and navigationDestination, it helps to study complete app structures. These iOS app templates give you larger projects to customize and learn from.
Pop to the root view in SwiftUI
This used to require workarounds with NavigationView. With NavigationStack, the solution is much more direct. Open ProductContentView and replace line 39 with viewModel.navigationStack.removeAll().
Because the path represents the screens in your navigation stack, removing all items from it takes the user back to the root.
Conclusion
NavigationStack, available starting with iOS 16, gives SwiftUI apps a cleaner way to build navigation driven by data. If your app doesn’t need to support older iOS versions, it can make deep linking and more complex navigation flows significantly easier to manage.
Compare the completed implementation with the original NavigationView version.