SwiftUI DataFlow
问题
- view 和 data 如何 two-way 绑定,View如何跟随Data的变化进行刷新
- view 和 data 声明周期
- 不同view之间如何share data
- @State @Binding @StateObject @ObserverableObject @ObserveredObject @EnvirmentObject 区别
为什么需要SwiftUI
graph TD
Code --> initialView
Code --> updateView
updateView --> updateVieww
updateView --> updateData
平时我们在code页面代码的时候,codepath并不是单一路径的,很多情况下,data和view不统一导致问题的产生。
为了编写维护性更高的代码。
graph TD
code --> data
data --> view
siggle code path,应呼声而出。
我们使用SwiftUI并不是说为了优化多少性能,而是提高代码的可维护性。使用框架避免问题的的发生。
SwiftUI的基本结构
struct SomeView: View {
var body: some View {
Text(" some view ")
}
}
所有的视图组件都是value类型的struct,随时随地rebuild.
如果这样的struct持有页面状态,当页面刷新的时候,所有的状态是否都会回归到默认状态?
这时候就需要我们property wrapper登场了
struct SomeView: View {
@State var someState = false
var someValue = ""
var body: some View {
Text(" some view ")
}
}
@State @Binding
graph TD
ContentView --> SomeView持有someValue
ContentViewObject --> SomeViewObject持有someState
- @State修饰的属性,不会由视图保存,而是另外保存。所以让视图rebuild的时候,视图的状态也不会丢失。
- 因为Swift中的属性都是值类型,所以如果多个视图想share state怎么办?
这时候就需要@binding 拿到 @state的引用。来share data.
struct SomeView: View {
@State var someState = false
var body: some View {
OtherView(someState: $someState)
}
}
struct OtherView: View {
@Binding var someState: Bool
var body: some View {
Text("")
}
}
如果我有很多State,如果处理?
这里就引入StateObject的概念
@StateObject @ObservedObject ObservableObject
类比@State声明单一属性,@StateObject可以修饰一个复杂的状态对象。状态对象里面的属性是否是State,可以足有控制。
- 遵循
ObservableObject
协议,使用@published
来Wrapper需要响应视图响应的属性 - value changed 必须在主线程
// 声明一个complexObject
class ComplexObject: ObservableObject {
// 可相应视图rebuild的state
@Published var someState = false
var someValue = true
}
// 持有complexObject
struct SomeView: View {
@StateObject var someStateObject = ComplexObject()
var body: some View {
OtherView(someStateObject: someStateObject)
}
}
// 仅使用
struct OtherView: View {
@ObservedObject var someStateObject: ComplexObject
var body: some View {
Text("")
}
}
这里有几个点讲一下
Q:为什么ComplexObject使用class
A: 因为ObservableObject必须遵循AnyObject,必须是class
Q: share State 不使用 $ 符号了
A: 因为是class,原本就是引用类型
Q: StateObject 和 ObservedObject的区别
A: 类似State 和 Binding,一个是持有使用状态,一个仅仅是使用状态
多视图share state需要视图初始化一个一个传递,也太麻烦了。所以引出我们的@EnvironmentObject
@EnvironmentObject
// 声明一个complexObject
class ComplexObject: ObservableObject {
// 可相应视图rebuild的state
@Published var someState = false
var someValue = true
}
// 持有complexObject
struct SomeView: View {
@StateObject var someStateObject = ComplexObject()
var body: some View {
//>>>>>>>>>>>>>>>>>>>>>>>看这里>>>>>>>>>>
OtherView()
.environmentObject(someStateObject)
//
}
}
// 仅使用
struct OtherView: View {
//>>>>>>>>>>>>>>>>>>>>>>看这里
@EnvironmentObject var someStateObject: ComplexObject
var body: some View {
Text("")
}
}
- 使用environmentObject的midifier注入对象
- 从EnvironmentObject取出对象
简单粗暴
参考
whats-the-difference-between-observedobject-state-and-environmentobject