The issue I'm facing is that my NavigationPath is always empty. The context is that I have 3 Views.
View A contains the NavigationStack and has two NavigationLinks, to View B and View C respectively.
View B has a NavigationLink to View C and a toolbar button to View A.
View C has a NavigationLink to View B and a toolbar button to View A.
struct ViewA: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Text("ViewA")
NavigationLink {
ViewB(path: $path)
} label: {
Text("Go to ViewB")
}
NavigationLink {
ViewC(path: $path)
} label: {
Text("Go to ViewC")
}
}
}
}
struct ViewB: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("ViewB")
NavigationLink {
ViewC(path: $path)
} label: {
Text("Go to ViewC")
}
}
.toolbar {
Button("ViewA") {
path = NavigationPath()
}
}
}
}
struct ViewC: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("ViewC")
NavigationLink {
ViewB(path: $path)
} label: {
Text("Go to ViewB")
}
}
.toolbar {
Button("ViewA") {
path = NavigationPath()
}
}
}
}
Variable path is always empty.
I've tried multiple implementations, still not working. I'm expecting to have the toolbar button send me to View A.
You need to use the value
parameter of the NavigationLink
in conjuction to the navigationDestination
modifier for the path State variable to be changed, or you could append objects that conform to the Hashable
protocol to navigate (the navigationDestination
is needed either way).
Here's an example:
struct ViewA: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack(spacing: 8) {
Text("ViewA")
NavigationLink(value: "B") {
Text("Go to B")
}
NavigationLink(value: "C") {
Text("Go to C")
}
}
/// Here you handle possible destinations for the String type
/// You can define other destinations for different types as well
.navigationDestination(for: String.self) { value in
switch value {
case "B": ViewB(path: $path)
case "C": ViewC(path: $path)
case "D": Text("View \(value)")
default:
Text("View not found")
}
}
}
}
}
And here are ViewB
and ViewC
:
struct ViewB: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
NavigationLink(value: "C") {
Text("Go to C")
}
}
.toolbar {
Button("ViewA") {
path = NavigationPath()
}
}
}
}
struct ViewC: View {
@Binding var path: NavigationPath
var body: some View {
VStack {
Text("ViewC")
Text("Go To D")
.foregroundStyle(.blue)
/// You can also append stuff to the path
.onTapGesture {
path.append("D")
}
}
.toolbar {
Button("ViewA") {
path = NavigationPath()
}
}
}
}
When you append values to the path the navigationDestination
callback for the type appended gets called. It took me a bit to get it when I first saw it but now it is pretty straightforward.
Let me know if you any doubts.