使用标签/选择或isActive进行NavigationView的程序化导航

时间:2020-05-20 18:34:38

标签: swiftui

NavigationLink具有一个初始化程序NavigationLink(destination:, tag:, selection:, label:),该初始化程序应该是一个隐藏的NavigationLink,在selection ==标签时可以激活。与NavigationLink(destination:isActive:label:)类似。

现在我想知道,我可以使用它在模型中拥有一个可用于在页面之间任意跳转的属性吗? Aka,是否要支持NavigationView的程序化导航?

类似这样的东西:

import SwiftUI

enum NavStep {
    case step1
    case step2
}

class NavModel: ObservableObject {
    @Published var step: NavStep? = .step1
}

struct Page1View: View {

    @EnvironmentObject var navModel: NavModel

    var body: some View {
        VStack(spacing: 20) {
            // Hidden link from Page1 -> Page2 that gets active when model.step is set to .step2
            NavigationLink(destination: Page2View(), tag: NavStep.step2, selection: $navModel.step) {
                EmptyView()
            }
            Text("Page 1")
            Button("Go to Page 2") {
                self.navModel.step = .step2
            }
        }
        .navigationBarTitle("Page 1")
    }

}

struct Page2View: View {

    @EnvironmentObject var navModel: NavModel

    var body: some View {
        VStack(spacing: 20) {
            Text("Page 2")
            Button("Go to Page 1") {
                self.navModel.step = .step1
            }
        }
        .navigationBarTitle("Page 2")
    }

}

struct ProgrammaticNavigationExample: View {

    var body: some View {
        NavigationView {
            Page1View()
        }
        .environmentObject(NavModel())
    }

}

struct ProgrammaticNavigationExample_Previews: PreviewProvider {
    static var previews: some View {
        ProgrammaticNavigationExample()
    }
}

很好,适用于两个页面,您可以通过设置step属性以编程方式导航。 但是,现在我想知道,如何将其扩展到另一个第三页?

当我尝试天真地执行此操作时,设置'model.step = .step3'会中断第一页中的导航链接,然后返回到第1页。即使我使用两个布尔属性'enteredStep2'/可以相应设置的“ enteredStep3”在尝试通过设置这些属性返回时会变得不稳定。

有什么想法可以使用此API启用编程导航(或以其他方式)?还是任何线索为何NavigationView / NavigationLink的行为与示例相同?

1 个答案:

答案 0 :(得分:1)

似乎目前无法使用此API在多个步骤上构建程序化导航(更多信息,请参见Asperis comment)。

您只能使用NavigationLink(destination:, tag:, selection:, label:)对下一个要显示的视图做出程序决定,例如:

struct ProgrammaticNavigationExampleView: View {

    enum NavDestination {
        case red
        case green
    }

    @State var destination : NavDestination?

    var body: some View {
        VStack(spacing: 20) {
            NavigationLink(destination: Color.red, tag: NavDestination.red, selection: $destination) {
                EmptyView()
            }
            NavigationLink(destination: Color.green, tag: NavDestination.green, selection: $destination) {
                EmptyView()
            }
            Text("Page 1")
            Button("Show random page") {
                self.destination = [.red, .green].randomElement()!
            }
        }
        .navigationBarTitle("Page 1")
    }

}

struct ProgrammaticNavigationExample_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            ProgrammaticNavigationExampleView()
        }
    }
}