
写前端习惯了,比较喜欢使用Pinia那种全局状态共享的功能,就尝试怎么实现,实现方式大概有四种,这四种都是比较简单的,分别是使用 @StateObject+@EnvironmentObject 和 @StateObject + @ObservedObject,还有@AppStorage 和 单利模式的ObservableObject这四种。
@StateObject+@EnvironmentObject方式
这种方式需要通过环境变量传递给子视图,并且子视图不持有这个数据状态
全局状态视图:
Swift
// 数据状态同步管理
class CounterModel: ObservableObject {
@Published var count: Int = 0
}
父视图:
Swift
struct ContentView: View {
@StateObject private var counter = CounterModel()
var body: some View {
VStack(spacing: 20) {
Text("父组件:当前计数:\(counter.count)")
.font(.title)
// 将 counter 传递给子组件
ChildView()
.environmentObject(counter)
}
.padding()
}
}
子视图:也可以通过onChange监听数据变化
Swift
struct ChildView: View {
@EnvironmentObject var counter: CounterModel
var body: some View {
Button("子组件按钮 +1") {
counter.count += 1
}
.padding()
.background(.blue.opacity(0.2))
.cornerRadius(10)
.onChange(of: counter.count) { _, _ in
print("count change")
}
}
}
@StateObject + @ObservedObject方式
这种方式需要通过父视图传递给子视图,并且子视图不持有这个数据状态
全局状态视图:
Swift
// 数据状态同步管理
class CounterModel: ObservableObject {
@Published var count: Int = 0
}
父视图:
Swift
struct ContentView: View {
@StateObject private var counter = CounterModel()
var body: some View {
VStack(spacing: 20) {
Text("父组件:当前计数:\(counter.count)")
.font(.title)
// 将 counter 传递给子组件
ChildView(counter: counter)
}
.padding()
}
}
子视图:
Swift
struct ChildView: View {
@ObservedObject var counter: CounterModel
var body: some View {
Button("加 1") {
counter.count += 1
}
.onChange(of: counter.count) { _, _ in
print("counter 变化")
}
}
}
@AppStorage方式
使用AppStorage的方式适合存储一些轻量数据,小量简单数据(如登录状态、语言、主题)。所有界面自动同步,不需要 ObservableObject,也支持使用 onChange 监听。并且数据是持久化存储在本地的,后面重启会恢复之前的数值。
Swift
struct ChildView: View {
// 接收环境对象(跨组件共享的数据)
@AppStorage("name") var name = ""
var body: some View {
Button("子组件按钮 +1") {
name += "1024小神"
}
.padding()
.background(.blue.opacity(0.2))
.cornerRadius(10)
.onChange(of: name) { _, _ in
print("name change")
}
}
}
单利模式的ObservableObject
创建一个全局的单实例类,用于全局的状态管理:
Swift
// 单利模式全局状态
class GlobalState: ObservableObject {
// 创建全局共享静态属性
static let shared = GlobalState()
// 防止外部创建
private init() {}
// 共享的数据
@Published var count: Int = 0
}
然后在任意view中都可以使用:并支持onChange监听
Swift
struct AnotherChildView: View {
// 全局状态
@ObservedObject var globalState = GlobalState.shared
var body: some View {
Text("另一个子组件:当前计数:\(globalState.count)")
.font(.headline)
.padding()
.onChange(of: globalState.count) { _, _ in
print("globalState.count发生了变化")
}
}
}