When a view is pushed to the stack via navigationDestination:isPresented, it is always the top view in the stack, even if another view is pushed afterward. Is that the expected behaviour?
In the following code, when tapping the button on page 1, page 2 is pushed to the stack. When the navigationLink on page 2 is pushed, page 3 is pushed to the stack, but page 2 is moved 2 the top. So it is still page 2 that is visible. Navigate back shows page 3.
struct ContentView: View {
@State var navigateToSecondPage = false
var body: some View {
NavigationStack {
VStack {
Text("1st page")
Button("Navigate to 2nd page") {
navigateToSecondPage = true
}
}
.navigationDestination(isPresented: $navigateToSecondPage) {
VStack {
Text("2nd page")
NavigationLink(value: SomeItem()) {
Text("Navigate to 3rd page")
}
}
}
.navigationDestination(for: SomeItem.self) { item in
Text("3rd page")
}
}
}
}
struct SomeItem: Hashable {
}
So after navigating to page 3 the stack looks like: ['page 1', 'page 3', 'page 2'] If the navigationLink is pressed again the stack looks like: ['page 1', 'page 3', 'page 3', 'page 2']
Is that as expected when using navigationDestination:isPresented and navigationDestination:for?
I'm not sure if this is expected, but as the docs for navigationDestination(isPresented:destination:)
say,
In general, favor binding a path to a navigation stack for programmatic navigation.
So I'm not surprised that there are cases that this doesn't work.
Take the advice and bind a NavigationPath
instead:
@State var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack {
Text("1st page")
Button("Navigate to 2nd page") {
// NavigationDestinations is an enum
path.append(NavigationDestinations.page2)
}
}
.navigationDestination(for: NavigationDestinations.self) { dest in
if dest == .page2 {
VStack {
Text("2nd page")
NavigationLink(value: SomeItem()) {
Text("Navigate to 3rd page")
}
}
}
}
.navigationDestination(for: SomeItem.self) { item in
Text("3rd page")
}
}
}