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

问题描述 投票:0回答:2

如何在 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")
}
swift xcode swiftui
2个回答
11
投票

使用 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
的人,切换到这个应该很容易,但结果却很痛苦。


3
投票

您应该使用

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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.