SwiftUI:NavigationLink 奇怪的行为
Posted
技术标签:
【中文标题】SwiftUI:NavigationLink 奇怪的行为【英文标题】:SwiftUI: NavigationLink weird behaviour 【发布时间】:2021-08-16 14:39:00 【问题描述】:我正在尝试建立一个商店以便在 SwiftUI 流程中导航。 这个想法是每个屏幕都应该观察状态并使用 NavigationLink 进入下一个屏幕。
它似乎适用于推送一个视图,但是当我将几个视图推送到堆栈中时,它开始表现得很奇怪:视图会自行弹出。
幸运的是,我能够在一个单独的项目中重现它。当我从 2 移动到 3 时,会出现第三个屏幕,但 NavigationView 会重置为其原始状态 (ContentView
):
import SwiftUI
@main
struct NavigationTestApp: App
var body: some Scene
WindowGroup
NavigationView
ContentView()
.navigationViewStyle(StackNavigationViewStyle())
class Store: ObservableObject
@Published var state: StoreState
struct StoreState
var flowState: FlowState = .none
enum FlowState
case none, one, two, three
enum Action
case moveTo1, moveTo2, moveTo3
init(state: StoreState)
self.state = state
func send(_ action: Action)
switch action
case .moveTo1:
state.flowState = .one
case .moveTo2:
state.flowState = .two
case .moveTo3:
state.flowState = .three
struct ContentView: View
@ObservedObject var store = Store(state: .init())
var body: some View
VStack
Button(action:
store.send(.moveTo1)
, label:
Text("moveTo1")
)
NavigationLink(
destination: ContentView1().environmentObject(store),
isActive: Binding(
get: store.state.flowState == .one ,
set: _ in
),
label:
)
struct ContentView1: View
@EnvironmentObject var store: Store
var body: some View
VStack
Button(action:
store.send(.moveTo2)
, label:
Text("moveTo2")
)
NavigationLink(
destination: ContentView2().environmentObject(store),
isActive: Binding(
get: store.state.flowState == .two ,
set: _ in
),
label:
)
struct ContentView2: View
@EnvironmentObject var store: Store
var body: some View
VStack
Button(action:
store.send(.moveTo3)
, label:
Text("moveTo3")
)
NavigationLink(
destination: ContentView3().environmentObject(store),
isActive: Binding(
get: store.state.flowState == .three ,
set: _ in
),
label:
)
struct ContentView3: View
@EnvironmentObject var store: Store
var body: some View
Text("Hello, world!")
.padding()
我错过了什么?
【问题讨论】:
尝试使用.isDetailLink(false)
,例如***.com/a/61707193/12299030
【参考方案1】:
我想出了一个解决方案。问题似乎是当您“移动到”下一个视图时,您的模型会从堆栈中弹出前一个视图。我(稍微)修改了它,以便系统现在可以确定导航堆栈上需要哪些视图。
不过,我不得不承认,我本来希望您的示例能够工作,因为我们只是声明堆栈中的(单个)视图。
因此,稍作修改的代码保留了导航堆栈上的先前视图(我还添加了一些打印语句以查看发生了什么):
import SwiftUI
class Store: ObservableObject
@Published var state: StoreState
struct StoreState
var flowState: FlowState = .none
enum FlowState: Int
case none = 0, one, two, three
enum Action
case moveTo1, moveTo2, moveTo3
init(state: StoreState)
self.state = state
func send(_ action: Action)
print("state: \(state), action: \(action)")
switch action
case .moveTo1:
state.flowState = .one
case .moveTo2:
state.flowState = .two
case .moveTo3:
state.flowState = .three
print("new state: \(state)")
struct ContentView: View
@ObservedObject var store = Store(state: .init())
var body: some View
VStack
Button(action:
print("moveTo1")
store.send(.moveTo1)
, label:
Text("moveTo1")
)
NavigationLink(
destination: ContentView1().environmentObject(store),
isActive: Binding(
get: store.state.flowState.rawValue >= Store.FlowState.one.rawValue ,
set: newValue in
store.state.flowState = .none
print("ContentView1: \(newValue)")
),
label:
)
struct ContentView1: View
@EnvironmentObject var store: Store
var body: some View
VStack
Button(action:
print("moveTo2")
store.send(.moveTo2)
, label:
Text("moveTo2")
)
NavigationLink(
destination: ContentView2().environmentObject(store),
isActive: Binding(
get: store.state.flowState.rawValue >= Store.FlowState.two.rawValue ,
set: newValue in
store.state.flowState = .one
print("ContentView2: \(newValue)")
),
label:
)
struct ContentView2: View
@EnvironmentObject var store: Store
var body: some View
VStack
Button(action:
print("moveTo3")
store.send(.moveTo3)
, label:
Text("moveTo3")
)
NavigationLink(
destination: ContentView3().environmentObject(store),
isActive: Binding(
get: store.state.flowState.rawValue >= Store.FlowState.three.rawValue ,
set: newValue in
store.state.flowState = .two
print("ContentView3: \(newValue)")
),
label:
)
struct ContentView3: View
@EnvironmentObject var store: Store
var body: some View
Text("Hello, world!")
.padding()
import PlaygroundSupport
PlaygroundPage.current.setLiveView(
NavigationView
ContentView()
.navigationViewStyle(StackNavigationViewStyle())
)
注意事项:
添加一个事件(又名操作)back
并确定视图模型中的新状态可能会更好,而不是让它在视图中执行。
【讨论】:
保持所有导航链接处于活动状态!就是这样!非常感谢:-)以上是关于SwiftUI:NavigationLink 奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 上的 NavigationLink 两次推送视图
SwiftUI:NavigationLink 内的水平 ScrollView 会中断导航
有没有办法向 NavigationLink 添加额外的功能? SwiftUI