Hi all! I encountered some strange behaviour that I cannot explain. When I have a NavigationStack
that is embedded in a TabView
, and that NavigationStack
uses a NavigationPath
that is stored within an ObservableObject
, and the view within the NavigationStack
gets its NavigationDestination
s via an extension on the View
object (either via a direct function or via a ViewExtension), the navigation doesn't work as expected, namely that back button seems to not pop views from the path. Consider the following example:
struct ContentView: View {
var body: some View {
TabView {
NavViewContainer1()
.tabItem {
Text("One")
}
NavViewContainer2()
.tabItem {
Text("Two")
}
}
}
}
@MainActor
class Model: ObservableObject {
@Published var path = NavigationPath()
}
struct NavViewContainer1: View {
@StateObject private var model = Model()
var body: some View {
NavigationStack(path: $model.path) {
VStack {
Text("1").font(.title).padding()
NavigationLink(value: "One") {
Text("Dest 1")
}
NavigationLink(value: "Two") {
Text("Dest 2")
}
}
.navigationDestination(for: String.self) { Text($0) }
}
}
}
struct NavViewContainer2: View {
@StateObject private var model = Model()
var body: some View {
NavigationStack(path: $model.path) {
VStack {
Text("2").font(.title).padding()
NavigationLink(value: "One") {
Text("Dest 1")
}
NavigationLink(value: "Two") {
Text("Dest 2")
}
}
.setUpDestinations()
}
}
}
extension View {
func setUpDestinations() -> some View {
navigationDestination(for: String.self) { Text($0) }
}
}
When clicking the destination buttons on the first tab (so in NavViewContainer1
, I can go to a child view, back to the root, then click the other link to go to a child view and back to the root, all good. The route taken looks like this: Root > Dest 1 > Root > Dest 2 > Root.
However, when I do the same in the second tab (NavViewContainer2
), as soon as I click on the second destination, it seems like the first destination was not removed from the path, since clicking the back button in the second destination brings me to the first destination. The route taken looks like this: Root > Dest 1 > Root > Dest 2 > Dest 1 > Root.
If I either move the view out of the TabView, move the path inside of the view with a @State
variable or as in view 1 add the navigationDestinations directly, the path works as expected. Only the combination of TabView + NavigationPath in ObservableObject + view extension yields this behaviour. Am I missing something here, or is this a bug in the SwiftUI framework?