struct View1: View {
var category: String
var body: some View {
NavigationStack {
List { ...
NavigationLink(value: category) {
Text("Link to View2")
}
}
.navigationDestination(for: String.self) { str in
View2(item: str)
}
}
}
}
struct View2: View {
var item: String
var body: some View {
NavigationStack {
List { ...
NavigationLink(value: category) {
Text("Link to View3")
}
}
.navigationDestination(for: String.self) { str in
View3(number: str)
}
}
}
}
struct View3: View {
var number: String
var body: some View {
List { ... }
}
}
In this code View1 when press one of the List item it says " there is no matching navigationDestination declaration visible from the location of the link. " But when I delete the NavigationStack bracket in the View2, then it works. Why is that?
And I want to put the path to the NavigationStack for going to the root. So I think I should leave the NavigationStack in the View2. Is it right? or is there another way?
Hi,
Is there a reason you need to nest one NavigationStack
inside another? The intended way to use it is to have one top-level NavigationStack
that contains multiple navigationDestination
- https://developer.apple.com/documentation/swiftui/view/navigationdestination(for:destination:) - modifiers that allow you to navigate to your next view based on the value, or to use other ways of destination like a NavigationLink
that contains a destination in it.
For your code, since you already have your items in a List
, you don't need another NavigationStack
. Also, you don't need two different navigationDestination
modifiers that both target Strings. If you want these to have different destinations, you can use different types as well to achieve this.
Here is your code with the above applied:
struct View1: View {
@State private var path: NavigationPath = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List(0..<3) { num in
//value is a String here
NavigationLink(value: num.description) {
Text("\(num.description) link to View2")
}
}
.navigationDestination(for: String.self) { str in
View2()
}
.navigationDestination(for: Int.self) { num in
View3()
}
}
}
}
struct View2: View {
var body: some View {
List(0..<4) { num in
//value is an Int here
NavigationLink(value: num) {
Text("\(num.description) link to View3")
}
}
}
}
struct View3: View {
var body: some View {
List(0..<3) { num in
Text(num.description)
}
}
}
The value presented in View1 is a String, so it will use the navigation destination modifier that targets Strings to go to View2. The value presented in View2 is an Int, so it will use the navigation destination modifier that targets Ints to go to View3. The NavigationPath will be in the top level NavigationStack, which is in View1