SwiftUI状态管理--Combine(Environment
2021-11-29 本文已影响0人
Mehmet
SwiftUI 已经如同前端vue、react 一般支持响应式编程。也有类似前端的
state
。如今swiftUI已经到2.0版本。swift 也已经5.5了 。所以现阶段从OC 切换到swift是一个非常合适的时机(有点晚)。了解swift 或者前端就会明白OC的笨重。作为一个已经使用了8年OC的开发来说,切换到swift无疑有着不舍。不过学习新的东西,总是充满了挑战。
通过最近的学习和使用特此整理。本文以实际使用出发。具体实现原理待后面研究源码再进行整理。
在实际项目中使用到的有:
- AppStorage
- Environment
- EnvironmentObject
- ObservedObject
- StateObject
Environment
值类型,当创建应用时,会自动创建Environment。其主要作用是传递系统的一些设置。如ColorScheme、NSManagedObjectContext。系统又很多对应的key可以查看EnvironmentValues获取key列表。
在需要使用的view中,只需要使用PropertyWrapper属性包装器 @Enviroment
import SwiftUI
struct HomePageView: View {
// colorScheme values: .light, .dark
@Enviroment(\.colorScheme) var colorScheme
var body: some View {
Text("Hello, World")
.foregroundColor(colorScheme = .light ? .yellow : .blue)
}
}
虽然系统自动创建,不过我们也可以自定义一个EnviromentKey,代码如下:
import Foundation
import SwiftUI
struct UserInfo {
var userName: String = ""
init(userName: String) {
self.userName = userName
}
}
struct UserInfoKey: EnvironmentKey {
static var defaultValue: UserInfo {
return UserInfo(userName: "lixxx")
}
}
extension EnvironmentValues {
var userInfo: UserInfo {
get { return self[UserInfoKey.self] }
set { self[UserInfoKey] = newValue }
}
}
在使用自定义的Environment时,要手动去注入到根视图上。并初始化注入对象为其设置一个值。
import SwiftUI
struct ContentView: View {
var body: some View {
TabbarPageView()
.environment(\.userInfo, UserInfo(userName: "liqingyu"))
}
}
EnvironmentObject
引用类型,和Environment作用相同,可操作性强,可以使用其为应用进行设置全局变量。共享数据于应用各个页面。
首先创建一个全局对象。因为我们要使用这个对象,并且可能会进行修改,修改后可能会刷新界面等操作。所以我们要观察这个对象 所以使用ObservableObject 协议 通过@Published 当值发生变化时通知全局作出响应。
import Foundation
class Person:ObservableObject {
@Published var name = ""
}
在根视图上进行注入,子视图将可以进行响应
import SwiftUI
struct ContentView: View {
var body: some View {
TabbarPageView()
.environmentObject(Person())
}
}
在需要使用的试图进行引入操作
import SwiftUI
struct EnvironmentPageView: View {
@EnvironmentObject var person: Person
var body: some View {
VStack{
Text("name: \(person.name)")
}
}
}
编辑操作,Binding值绑定 及 = 属性设置都是可以的
import SwiftUI
struct EnvironmentDetailView: View {
@EnvironmentObject var person: Person
var body: some View {
TextField("Person", text: $person.name)
.padding(20)
.navigationBarTitleDisplayMode(.inline)
.onAppear(){
person.name = "liqngyu"
}
}
}