如何在 SwiftUI 中使用 .navigationDestination 和 Button 来实现复杂的导航场景?

Eti*_*nne 9 xcode swift swiftui

如何在 SwiftUI 中使用 .navigationDestination 和 Button 来实现复杂的导航场景?

我目前正在 SwiftUI 中开发一个设置页面,该页面大约有 10 个按钮。由于需要自定义设计,这些按钮中的每一个都不位于 ForEach 或 List 中,并且每个按钮都需要导航到不同的视图,并在它们之间传递不同的变量。

在过去,我会使用 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()
    })
}
Run Code Online (Sandbox Code Playgroud)

第二个视图:

Button(action: {
    isPresented = true //Goes to third view
}) {
    Text("Navigate to third view")
}
.navigationDestination(isPresented: $isPresented, destination: ThirdView())
Run Code Online (Sandbox Code Playgroud)

第三视图:

Button(action: {
    isPresented = false //Goes back to second view, however, this seems not to work
}) {
    Text("Navigate Back to second view")
}
Run Code Online (Sandbox Code Playgroud)

Eti*_*nne 4

使用 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这对某人有帮助,因为我为此头痛了好几天。作为一个经常使用NavigationView&的人NavigationLink,切换到这个应该很容易,但结果却很痛苦。