SwiftUI Tutorial

How to implement NavigationStack in SwiftUI

Replace NavigationView with SwiftUI’s data-driven NavigationStack and gain more control over complex navigation flows, deep links, and returning to your root view.

SwiftUINavigationStack

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.

Start with the NavigationView project

Download the original sample project and open DashboardContentView to follow along.

Download project
Step 1

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.

NavigationStack does not require a path, but using one is what makes it especially versatile. You can add items to the path or replace the path entirely to create a different navigation stack.
Step 2

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.

Step 3

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.

iOS App Templates

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.

Step 4

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.

Download the finished NavigationStack project

Compare the completed implementation with the original NavigationView version.

Download project

Need help building your iOS app?

Apps4World provides custom native iOS development in Swift, SwiftUI, and UIKit — from the first screen through App Store delivery.

Discuss your project