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发生了变化")
            }
    }
}
相关推荐
2501_916007471 天前
如何查看 iOS 设备系统与硬件信息,iOS系统信息显示工具
android·ios·小程序·https·uni-app·iphone·webview
2501_916007471 天前
iOS APP 开发,从项目创建、证书与描述文件配置、安装测试和IPA 上传
android·ios·小程序·https·uni-app·iphone·webview
Swift社区1 天前
在Swift中实现允许重复的O(1)随机集合
开发语言·ios·swift
大熊猫侯佩2 天前
拯救巴别塔:WWDC24 全新 Translation API 实战
swiftui·wwdc·language·coreml·translation api·翻译接口·translationsess
初级代码游戏2 天前
iOS开发 SwiftUI 8:NavigationView 导航
ios·swiftui·swift
美狐美颜SDK开放平台2 天前
跨平台开发实战:直播美颜sdk动态贴纸在 Android / iOS / HarmonyOS 的落地方案
android·ios·harmonyos·美颜sdk·直播美颜sdk·视频美颜sdk·美颜api
2501_916008892 天前
在不越狱前提下导出 iOS 应用文件的过程,访问应用沙盒目录,获取真实数据
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_915106322 天前
Android和IOS 移动应用App图标生成与使用 Assets.car生成
android·ios·小程序·https·uni-app·iphone·webview
虹少侠2 天前
基于 WebKit 构建 macOS 多浮窗视频播放的技术实践(含完整产品落地)
前端·macos·swift·webkit
2501_915918412 天前
Mac 抓包软件有哪些?Charles、mitmproxy、Wireshark和Sniffmaster哪个更合适
android·ios·小程序·https·uni-app·iphone·webview