Swift中跨view视图组件实现全局状态共享的方式汇总

写前端习惯了,比较喜欢使用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发生了变化")
            }
    }
}
相关推荐
用户223586218201 天前
WebKit WebPage API 的引入尝试与自研实现
ios
啦啦啦!1 天前
ChatGPT和Gemini的接入和封装
人工智能·ios·chatgpt
报错小能手1 天前
ios开发方向——swift并发进阶核心 async/await 详解
开发语言·ios·swift
开心就好20251 天前
HTTPS超文本传输安全协议全面解析与工作原理
后端·ios
牛马1111 天前
Flutter iOS 权限配置完整指南(定位权限)
flutter·ios
A_QXBlms1 天前
多账号轮询架构 — 利用企销宝iPad协议突破单账号群发次数限制
ios·架构·ipad
用户79457223954131 天前
【Lottie】让设计稿上的动效直接"活"在 App 里
swiftui·swift
HH思️️无邪1 天前
Flutter + iOS 实战指南:教程视频 PiP + 退桌面(可复用模板)
flutter·ios
亘元有量-流量变现1 天前
深度技术对比:Android、iOS、鸿蒙(HarmonyOS)权限管理全解析
android·ios·harmonyos·方糖试玩
sunz_dragon1 天前
iPhone_签到App_自动化实战
ios·自动化·iphone