问题
NavigationLink has an initializer NavigationLink(destination:, tag:, selection:, label:) that is supposed to be a hidden NavigationLink that gets active when selection == tag. Similiar to NavigationLink(destination:isActive:label:).
Now I wondered, could I use this to have a property in a model that can be used to jump between pages arbitrarily? Aka, to support programatic navigation for NavigationView?
Something like this:
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()
}
}
Very well, works for two pages, you can navigate programatically by setting the step property. But, now I wondered, how could this be extended to another, third page?
When I try to do this naively, setting 'model.step = .step3' breaks the navigation link in the first page and we're back to page 1. Even if I model this using two boolean properties 'enteredStep2' / 'enteredStep3' that could be set accordingly it gets flaky when trying to go back by setting these properties.
Any ideas how programmatic navigation could be enabled with this API (or in some other way)? Or any clue why NavigationView/NavigationLink behaves like it does for the examples?
回答1:
It seems it is currently not possible to use this API to build programatic navigation over multiple steps (see Asperis comment for more information).
You can only use NavigationLink(destination:, tag:, selection:, label:) to make a programmatic decision on what View to show next, like:
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()
}
}
}
来源:https://stackoverflow.com/questions/61920405/programatic-navigation-for-navigationview-using-tag-selection-or-isactive