SwiftUI 核心选型:class + ObservableObject VS struct + @State

SwiftUI 的状态管理,本质是数据驱动 UI。但在实际开发中,一个绕不开的问题是:

👉 到底该用 struct + @State,还是 class + ObservableObject?

这不是语法选择,而是数据生命周期 + 共享方式的设计问题。


一句话结论

  • 局部、私有、短生命周期状态 → @State

  • 跨视图共享、可复用、可观察状态 → ObservableObject


1. @State:View 私有状态(值语义)

复制代码
struct CounterView: View {
    @State private var count = 0
    
    var body: some View {
        Button("\(count)") {
            count += 1
        }
    }
}

特点

  • 只能在当前 View 内使用

  • SwiftUI 持有并管理生命周期

  • 值类型(struct),更新即触发 View 重建

  • 不适合跨 View 传递

本质

@State 是 View 的本地状态缓存,SwiftUI 会在 View 重建时帮你"记住"它。

👉 可以理解为:"UI 内部状态"


2. ObservableObject:可共享状态(引用语义)

复制代码
class CounterModel: ObservableObject {
    @Published var count = 0
}

struct CounterView: View {
    @StateObject private var model = CounterModel()
    
    var body: some View {
        Button("\(model.count)") {
            model.count += 1
        }
    }
}

特点

  • 引用类型(class)

  • 多个 View 可以共享

  • @Published 自动触发 UI 更新

  • 生命周期由 @StateObject / @ObservedObject 控制

本质

👉 一个外部数据源(Source of Truth)


3. 核心差异对比

维度 @State ObservableObject
类型 struct(值) class(引用)
作用域 当前 View 多 View 共享
生命周期 SwiftUI 管理 你控制
数据传递 不支持 支持
适用场景 UI 状态 业务状态

4. 关键设计问题:谁拥有数据?

这是选型的核心。

✅ 用 @State 的情况

  • toggle / 输入框 / 动画状态

  • UI 层临时数据

  • 不需要跨组件

    @State private var isLoading = false

👉 View 自己拥有状态


✅ 用 ObservableObject 的情况

  • 用户信息

  • 网络请求结果

  • 跨页面数据共享

    class UserStore: ObservableObject {
    @Published var user: User?
    }

👉 状态独立于 View 存在


5. 常见误区

❌ 误区 1:所有状态都用 ObservableObject

问题:

  • 过度抽象

  • 性能变差(不必要的刷新)

  • 代码复杂

👉 UI 局部状态没必要上升为全局状态


❌ 误区 2:用 @State 管理复杂模型

复制代码
@State var user = User(...)

问题:

  • 数据难共享

  • 更新链条混乱

👉 复杂数据 = ObservableObject


❌ 误区 3:错误使用 @ObservedObject

复制代码
@ObservedObject var model = CounterModel() // ❌

问题:

  • View 重建 → model 被重建 → 状态丢失

👉 应该用:

复制代码
@StateObject private var model = CounterModel()

6. 进阶:组合使用(推荐)

实际项目中,一般是组合:

复制代码
struct ProfileView: View {
    @StateObject var userStore = UserStore()
    @State private var isEditing = false
}
  • userStore → 业务数据

  • isEditing → UI 状态

👉 分层清晰,职责明确


7. 设计哲学总结

  • @State:UI 的"感觉"

  • ObservableObject:业务的"事实"

或者更直接一点:

👉 View 应该轻,状态应该分层


8. 实战建议(工程视角)

  • 小组件优先 @State

  • 页面级数据用 @StateObject

  • 跨页面用 EnvironmentObject

  • 不要让 View 持有复杂业务逻辑


最后一句

SwiftUI 不是在问"用哪个",而是在问:

👉 你的数据,属于谁?活多久?要不要共享?

想清楚这三点,选型自然就出来了。

相关推荐
茶底世界之下11 小时前
Metal 冷启动并发下,Pipeline Cache 为什么必须合并在途编译
ios·swift
weixin_4038101312 小时前
用 Python 调 EasyClick iOS 免越狱脚本:开放接口对接步骤与参数
ios·iphone
weixin_4038101314 小时前
EasyClick iOS 免越狱自动化脚本怎么写:从环境判断到跑通第一个脚本
运维·ios·自动化
weixin_4038101315 小时前
不用越狱也能批量控制 iPhone:EasyClick iOS 免越狱脚本实战
ios·iphone
weixin_4038101316 小时前
iOS 自动化脚本怎么输入文字:代理、输入法与快捷指令三级方案
运维·ios·自动化
黑科技iOS上架2 天前
双引擎解决oc/swift开发引用加固难题
开发语言·ios·swift·审核·ios混淆·执行程序差异化
wechatbot8882 天前
企微第三方自动化开发:原生能力无阉割 API 开放平台介绍
后端·ios·微信·企业微信·ai编程·ipad
黑科技iOS上架2 天前
iOS framework/dylib动态库定向加固实战
macos·ios·objective-c·cocoa·审核·ios混淆·执行程序差异化
传奇开心果编程2 天前
【现代声明式UI学与练】第1课 从命令式UI到声明式UI
学习·flutter·ui·swiftui·react·android jetpack