如何在 SwiftUI 中使用 .navigationDestination 和 Button 来实现复杂的导航场景?
我目前正在 SwiftUI 中开发一个设置页面,该页面大约有 10 个按钮。由于需要自定义设计,这些按钮中的每一个都不位于 ForEach 或列表中,并且每个按钮都需要导航到不同的视图,并在它们之间传递不同的变量。
在过去,我会使用 NavigationLink(destination:label) 来实现此目的,虽然此方法仍然有效,但我遇到了问题。在其中一个或多个视图中,我需要使用 NavigationLink(isActive),该功能现已弃用。
我使用 .navigationDestination 发现了一个可能更好的解决方案,但我无法使其按预期工作。例如,我发现,如果在 NavigationLink 子视图中使用视图,则在调用完成后,它不会以编程方式关闭视图。
我在网上找到的大多数 SwiftUI 教程和资源都演示了使用 List 和 ForEach 以及以编程方式生成的数据进行导航,但不是像我的场景中那样简单的按钮单击。我看过无数的视频,甚至苹果文档,但不明白与这种类型的新导航有什么关系。
有人可以解释如何在这种情况下正确使用 .navigationDestination 及其要求吗?具体来说,如何将它与 Button(action:label) 一起使用来导航到下一个视图,以及它在 NavigationLink 子视图中的行为如何?
有关此事的任何帮助或指导将不胜感激。这是我想要实现的目标的简化示例:
第一眼:
NavigationStack() {
NavigationLink(label: {
Text("Navigate To Second View")
}, destination: {
SecondView()
})
}
第二个视图:
Button(action: {
isPresented = true //Goes to third view
}) {
Text("Navigate to third view")
}
.navigationDestination(isPresented: $isPresented, destination: ThirdView())
第三种观点:
Button(action: {
isPresented = false //Goes back to second view, however, this seems not to work
}) {
Text("Navigate Back to second view")
}
使用 Eilons 的答案,我能够成功地使其发挥作用。不过导致了
Only root-level navigation destinations are effective for a navigation stack with a homogeneous path.
的错误,调整了一下,头疼了几天,终于找到答案了。
首先,我去掉了
enum
,因为它对我所做的来说是多余的。我首先添加了一个 @State private var path = NavigationPath()
而不是 @State private var navigationPath: [Route] = []
数组。
这是完整的代码:
struct View1: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
Button("Go to view 2") {
path.append("View2")
}
.background(Color.red)
.navigationDestination(for: String.self) { route in
switch route {
case "View2":
View2(path: $path)
case "View3":
View3(path: $path)
}
}
}
}
}
struct View2: View {
@Binding var path: NavigationPath
var body: some View {
Button("Go to view 3") {
path.append("View3")
}
.background(Color.orange)
}
}
struct View3: View {
@Environment(\.dismiss) private var dismiss
@Binding var path: NavigationPath
var body: some View {
Button("Pop view") {
path.removeLast()
// or - call `dismiss()`
// dismiss()
}
.background(Color.green)
}
}
我希望这对某人有帮助,因为我为此头痛了好几天。作为一个一直使用
NavigationView
和 NavigationLink
的人,切换到这个应该很容易,但结果却很痛苦。
您应该使用
NavigationPath
。
enum Route {
case view2
case view3
}
struct View1: View {
@State private var navigationPath: [Route] = []
var body: some View {
NavigationStack(path: $navigationPath) {
Button("Go to view 2") {
navigationPath.append(.view2)
}
.background(Color.red)
.navigationDestination(for: Route.self) { route in
switch route {
case .view2:
View2(navigationPath: $navigationPath)
case .view3:
View3(navigationPath: $navigationPath)
}
}
}
}
}
struct View2: View {
@Binding var navigationPath: [Route]
var body: some View {
Button("Go to view 3") {
navigationPath.append(.view3)
}
.background(Color.orange)
}
}
struct View3: View {
@Environment(\.dismiss) private var dismiss
@Binding var navigationPath: [Route]
var body: some View {
Button("Pop view") {
navigationPath.removeLast()
// or - call `dismiss()`
// dismiss()
}
.background(Color.green)
}
}