SwiftUI数据状态和绑定
SwiftUI 数据状态和绑定
方案 | 说明 | 备注 |
---|---|---|
@State & @Binding |
提供 View 内部的状态存储 | 应该是被标记为 private 的简单值类型,仅在内部使用。 |
ObservableObject & @ObservedObject |
针对跨越 View 层级的状态共享 | 处理更复杂的数据类型,在数据变化时触发界面刷新。 |
@EnvironmentObject |
对于 “跳跃式” 跨越多个 View 层级的状态 | 更方便地使用 ObservableObject,以简化代码。 |
@State
& @Binding
Parent view:
1 | struct ParentView: View { |
Child view:
1 | struct ChildView: View { |
运行效果:
##@ObservedObject
Model:
1 | class Model: ObservableObject { |
注意,@Published
是个 internal 的。在 Xcode 工程里没事,但在 Playground 的 Sources 里写是必须 public 的,这时可以采用下面这种手动处理的方法:
1 | import Combine |
let objectWillChange = PassthroughSubject<Void, Never>()
用来实现ObservableObject
协议;- 给每个需要
@Published
的变量加willSet { objectWillChange.send() }
。
Parent View:
1 | public struct ParentView: View { |
Child View:
1 | public struct ChildView: View { |
这里其实是利用 class 的“传引用”特性来让子访问到父的 model 的,没什么特殊的。
##@EnvironmentObject
沿用上面 ObservableObject
的 Model:
1 | class Model: ObservableObject { |
Parent View:
1 | public struct ParentView: View { |
Child View:
1 | public struct ChildView: View { |
调用 Parent 的 View:
1 | ParentView().environmentObject(Model()) |
用 EnvironmentObject 让所有子都访问到父的 Model,可以避免逐层手动传递对象。
完整源码实现:SwiftUIDataStateAndBinding.playground。
参考
王巍 (@onevcat)《SwiftUI 与 Combine 编程》Chapter 3:数据状态和绑定