Reading time: 1 min
This quick recipe shows how to support nested NavigationLinks and allow the user to move back programatically. As always, SwiftUI throws a curveball even on trivial tasks such as this.
Here's what the end result looks like:

OK, so the situation you have is as following:
- You have a multi-level push navigation implemented with
NavigationLinks that are triggered programatically - either with booleanisActive:or optional-Identifiableusingtag:selection:. - You wish to manually navigate back from one of those screens to the previous one without using the built-in back button.
Here's some code that describes the setup:
struct NavPopTestingRoot: View {
@State private var isShown = false
var body: some View {
NavigationView {
NavigationLink("Next", isActive: $isShown) {
NavPopTesting(previousIsShown: $isShown)
}
}
}
}
struct NavPopTesting: View {
@Binding var previousIsShown: Bool
@State private var isShown = false
var body: some View {
VStack {
Button("Back") {
previousIsShown = false // dismiss programatically
}
NavigationLink("Next", isActive: $isShown) {
NavPopTesting(previousIsShown: $isShown)
}
}
.navigationBarBackButtonHidden(true)
}
}
Now, if you try running it, it works fine for the first dismiss - but for all subsequent ones, setting the isActive binding to false or the selection binding to nil doesn't work - the screen isn't dismissed:

To work around this, add an .isDetailLink(false) modifier to each NavigationLink:
// ...
NavigationLink("Next", isActive: $isShown) {
NavPopTesting(previousIsShown: $isShown)
}
.isDetailLink(false) // HERE
// ...
After that, everything will work as expected:

SwiftUISegues framework has this already taken care of when you're using push segues!