A First Look at SwiftUI NavigationStack, NavigationPath, and “navigationDestination” | by Anupam Chugh | Jun, 2022

Say goodbye to SwiftUI NavigationView with iOS 16

Photo by Dan Chung on Unsplash

SwiftUI NavigationView has been an Achilles heel of the framework since the beginning. From not letting lazy loads of destination views inside NavigationLink initially (though this was resolved later), to its inability to programmatically navigate deep links, SwiftUI’s Navigation framework often forced us to fall back to using the UINavigationController.

To our respite, with iOS 16, Apple has proposed a new navigation architecture that’s data-driven instead of the view-driven structure previously.

The major new Navigation API changes include a new NavigationStack that lets you push and pop views from a stack, a NavigationPath for managing the routing stack, and a navigationDestination modifier for efficiently navigating views programmatically. With the same update, they’ve deprecated NavigationView.

Integrating a NavigationStack in our view hierarchy stack is plain simple:

NavigationStack {
NavigationLink {
Text("Destination Screen")
} label: {
Text("Goto Next Screen")

We can directly refactor our old NavigationView with the new NavigationStack container in some trivial cases. Do notice the new NavigationLink init syntax though.

The API now contains a valuelabel syntax with the label hosting the content’s view for the link and the value containing the destination view builder.

It’s also worth noting that the NavigationLink’s older init methods like NavigationLink(isActive:destination:label:) has been deprecated.

Similarly NavigationLink(destination:tag:selection:) is also deprecated in iOS 16, which means refactoring programmatic navigation based on NavigationLink would require an altogether different code.

In the previous section, we saw how to set the destination view of NavigationLink within the init code itself. However, you might recall the pain isActive boolean flags gave us when constructing complex navigation structures before iOS 16.

Gladly, starting in iOS 16 we can set the destination view inside the .navigationDestination modifier. navigationDestination gives us the power to programmatically route to different screens based on the type. You can also add multiple navigationDestination modifiers for different view types.

In the below example, we’ve created a SwiftUI navigation app that builds the same list view on the destination screen:

Previously, to route NavigationLink we had tags.

With iOS 16, we’ve got a powerful new NavigationPath that can hold type erased data pertaining to the views displayed in the NavigationStack.

The power of NavigationPath lies in its ability to easily push, pop views that belong to different data types from the stack.

Consider the below application where we’ve plugged in the NavigationPath inside our NavigationStack:

We’ve set our NavigationPath inside an ObservableObject class and set it in an EnvironmentObject in order to pass it down to child views. Though, you can also use @Binding for the same.

Take notice of the modified NavigationStack(path:) init.

Here’s the code for the RowListsView:

We’ve slightly modified the above SwiftUI view — to incorporate custom back buttons that’ll programmatically change the NavigationPath — which in turn changes the view NavigationStack:

1*56p5lByOpvex Cb9o6Cq w
SwiftUI NavigationPath

We saw how easy it is to pop back to the root by invoking the following piece of code:

router.path = .init()

While that concludes this introductory post to the new SwiftUI NavigationStack, you can do so much more using the new patterns — like handle deep linking and more.

Also, to backport the new Navigation APIs to the prior iOS versions here’s an amazing open-source library.

That’s all for now. Here’s the gist for the entire SwiftUI code snippet.

News Credit

%d bloggers like this: