SwiftUI 的 NavigationLink 提供了一种通过状态变量(例如布尔值或标签)触发的程序化导航方式

45 min read

第一个示例使用布尔型状态变量 isShowingDetailView 来控制是否跳转到详细视图。当点击 "Tap to show detail" 按钮时,isShowingDetailView 被设置为 true,这将触发 NavigationLink,导航到 "Second View"。当 isShowingDetailView 设置为 false 时,将关闭 "Second View"。

第二个示例演示了多目标导航的情况,使用了一个可选字符串 selection 作为状态变量,通过给这个变量设置不同的字符串值("A" 或 "B"),来触发与之绑定的 NavigationLink,从而跳转到不同的目标视图("View A" 或 "View B")。

示例如下:

struct ContentView: View {
    @State private var isShowingDetailView = false
    @State private var selection: String? = nil
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Button("Tap to show detail") {
                    isShowingDetailView = true
                }
                
                Button("Go to View A") {
                    selection = "A"
                }
                
                Button("Go to View B") {
                    selection = "B"
                }
                
                Spacer()
            }
            .navigationTitle("Navigation Examples")
            .sheet(isPresented: $isShowingDetailView) {
                SecondView(isPresented: $isShowingDetailView)
            }
            .navigationBarItems(trailing: NavigationLink(destination: SecondView(isPresented: $isShowingDetailView), isActive: $isShowingDetailView) {
                EmptyView()
            })
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarBackButtonHidden(true)
            .navigationBarItems(leading: Button(action: {
                isShowingDetailView = false
            }) {
                Text("Back")
            })
            .navigationBarItems(trailing: Menu {
                Button("Option 1") {}
                Button("Option 2") {}
                Button("Option 3") {}
            } label: {
                Image(systemName: "ellipsis.circle")
            })
            .background(NavigationLink(destination: ViewA(), tag: "A", selection: $selection) {
                EmptyView()
            })
            .background(NavigationLink(destination: ViewB(), tag: "B", selection: $selection) {
                EmptyView()
            })
        }
    }
}

struct SecondView: View {
    @Binding var isPresented: Bool
    
    var body: some View {
        VStack {
            Text("Second View")
                .font(.headline)
                .padding()
            
            Button("Dismiss") {
                isPresented = false
            }
        }
    }
}

struct ViewA: View {
    var body: some View {
        Text("View A")
            .font(.headline)
            .padding()
    }
}

struct ViewB: View {
    var body: some View {
        Text("View B")
            .font(.headline)
            .padding()
    }
}