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 不是在问"用哪个",而是在问:
👉 你的数据,属于谁?活多久?要不要共享?
想清楚这三点,选型自然就出来了。