Reputation: 1248
How can I pop to root
in the new NavigationStack
in IOS 16 while using many NavigationLink
's inside other NavigationLink
?
Here is a solution for using the NavigationLink(_ title, value: )
, but once I try to build out Views
with more NavigationLink
's inside the .navigationDestination
the NavigationStack
gives the error A navigationDestination for MyApp.DataObject was declared earlier on the stack. Only the destination declared closest to the root view of the stack will be used.
struct DataObject: Identifiable, Hashable {
let id = UUID()
let name: String
}
@available(iOS 16.0, *)
struct ContentView8: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Text("Root Pop")
.font(.largeTitle)
.foregroundColor(.primary)
NavigationLink("Click Item", value: DataObject.init(name: "Item"))
.listStyle(.plain)
.navigationDestination(for: DataObject.self) { course in
Text(course.name)
NavigationLink("Go Deeper", value: DataObject.init(name: "Item"))
Button("Back to root") {
path = NavigationPath()
}
}
}
.padding()
}
}
Here is an example of the error from attempting the above approach. Adding the View within the NavigationLink
that has another NavigationLink
seems to give the error.
struct NavObj: Identifiable, Hashable {
let id = UUID()
let name: String
}
@available(iOS 16.0, *)
struct ContentView881: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack() {
NavigationLink(destination: T0121(test: 1), label: {Text("Click")})
}
}
}
@available(iOS 16.0, *)
struct T0121: View{
@State var test: Int
var body: some View{
VStack{
Text(String(test))
NavigationLink(value: NavObj.init(name: "Next"), label: {Text("Click")})
.navigationDestination(for: NavObj.self) { item in
T0121(test: 2)
}
}
}
}
Since I have many views within other views I assume I should stick with NavigationLink(destination, label)
, but the following logic to pop to root which works for NavigationView
does not work on the NavigationStack
:
@available(iOS 16.0, *)
struct ContentView: View {
@State private var isActive = false
var body: some View {
NavigationStack{
NavigationLink(destination: TestView(test: 1, isActive: $isActive), isActive: $isActive, label: {Text("Click")})
}
}
}
@available(iOS 16.0, *)
struct TestView: View{
@State var test: Int
@Binding var isActive: Bool
var body: some View{
VStack{
Text(String(test))
NavigationLink(destination: TestView(test: test+1, isActive: $isActive), label: {Text("Click")})
Button(action: {
isActive = false
}, label: {
Text("Root")
})
}
}
}
I apologize for making such a long question, I just wanted to make the issue very clear with plenty of examples. Thank you for any help!!!
Upvotes: 3
Views: 1791
Reputation: 53181
The correct way to handle pop-to-root in iOS 16, is to use a NavigationStack
with a path
, The problem seems to be that the navigationDestination
modifier in your example is applied to the NavigationLink
itself, it should be applied to the view at the top of the stack that contains the NavigationLink
(e.g. List
).
So you can fix your second example:
struct NavObj: Identifiable, Hashable {
let id = UUID()
let name: String
}
struct ContentView881: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack() {
VStack {
NavigationLink(destination: T0121(test: 1), label: {Text("Click")})
}
.navigationDestination(for: NavObj.self) { item in
T0121(test: 2)
}
}
}
}
struct T0121: View{
@State var test: Int
var body: some View{
VStack{
Text(String(test))
NavigationLink(value: NavObj.init(name: "Next"), label: {Text("Click")})
}
}
}
Upvotes: 1