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发生了变化")
            }
    }
}
相关推荐
开心就好202514 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
开心就好202517 小时前
免 Xcode 的 iOS 开发新选择?聊聊一款更轻量的 iOS 开发 IDE kxapp 快蝎
后端·ios
恋猫de小郭20 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
东坡肘子1 天前
OpenClaw 不错,但我好像没有那么需要 -- 肘子的 Swift 周报 #125
人工智能·swiftui·swift
忆江南2 天前
iOS 深度解析
flutter·ios
没有故事的Zhang同学2 天前
05-主题|事件响应者链@iOS-应用场景与进阶实践
ios
FeliksLv2 天前
尝试给Lookin 支持 MCP
ios
没有故事的Zhang同学2 天前
01-研究系统框架@Web@iOS | JavaScriptCore 框架:从使用到原理解析
ios
CocoaKier4 天前
苹果谷歌商店:如何监控并维护用户评分评论
ios·google·apple
iOS日常4 天前
iOS设备崩溃日志获取与查看
ios·xcode