Perhaps I am not understanding NavigationStack well and hope someone can help me.
I've setup a small example to demonstrate the issue:
@main
struct StacksApp: App {
var body: some Scene {
WindowGroup {
ViewA(someText: "Root View")
}
}
}
ViewA (AKA Root View)
struct ViewA: View {
private let someText: String?
private let someNumber: Int?
@State private var navigationPath = NavigationPath()
init(someText: String? = nil,
someNumber: Int? = nil) {
self.someText = someText
self.someNumber = someNumber
}
var body: some View {
NavigationStack(path: $navigationPath) {
VStack(spacing: 10) {
if let someText {
Text("Showing \(someText) text")
} else if let someNumber {
Text("Showing \(someNumber) number")
}
NavigationLink("Show View B", value: "ViewB")
}
.navigationDestination(for: String.self) { value in
if value == "Hello" {
ViewA(someText: value)
} else {
ViewB(path: $navigationPath)
}
}
.navigationDestination(for: Int.self) { value in
ViewA(someNumber: value)
}
}
}
}
ViewB
struct ViewB: View {
@Binding var path: NavigationPath
var body: some View {
VStack(spacing: 10) {
Text("Hello, World!, this is View B!")
NavigationLink("Go to ViewA - Showing Int value", value: 4)
NavigationLink("Go to viewA Showing text Value", value: "Hello")
}
.navigationDestination(for: Int.self) { value in
ViewA(someNumber: value)
}
}
}
The Problem
From ViewB I am unable to go to ViewA with different data - eg an Int. When I tap on "Go to ViewA - Showing Int value" or "Go to ViewA - Showing text value"
What happens is a new View is pushed on to the stack and then it pops me back to the original ViewA:
ViewA(someText: "Root View")
If I were to replace ViewA with some other view that I was to show multiple times, with different data - eg ViewB - there is no issue and it works as expected.
Is this by design? Eg pushing a root view multiple times not being allowed?
The problem is that the
NavigationStackis part ofViewA. When you navigate to anotherViewA, you get a newNavigationStackthat is nested in the existing one. This causes the problems you describedViewAshould not contain aNavigationStack- it should just be the view you put inside theNavigationStack { ... }.The
NavigationStackshould go in another view. Note that the navigation destinations should also go here, otherwise you would end up having multiple navigation destinations for the same type, whenViewAis pushed for the second time.