6-9.【架构设计】@State、@StateObject、@ObservedObject、@EnvironmentObject 如何说清楚它们的所有权模型?

1 阅读2分钟

一、四句话(所有权模型一句话版)

  • @State
    👉 “这个值的所有权在 View 自己,生命周期由 SwiftUI 管理。”
  • @StateObject
    👉 “这个引用类型对象由当前 View 创建并拥有,只创建一次。”
  • @ObservedObject
    👉 “这个对象不是我创建的,我只是临时观察它。”
  • @EnvironmentObject
    👉 “这个对象由更高层统一拥有,我只是从环境里拿来用。”

如果你只记住这四句,80% 场景已经不会踩雷。


二、把“所有权”翻译成三个问题(最关键)

每次选属性包装器,只问自己这三件事:

  1. 是谁创建的?
  2. 谁负责活多久?
  3. View 消失时,它要不要跟着消失?

三、完整对照表(所有权 + 生命周期)

包装器谁创建谁拥有生命周期绑定典型用途
@StateViewSwiftUI State StoreView identity简单值类型状态
@StateObjectViewViewView identity(一次)ViewModel / Store
@ObservedObject外部外部外部决定子 View 观察
@EnvironmentObject根容器全局环境App / Scene全局共享状态

四、最容易混淆的两个(重点)

1️⃣ @StateObject vs @ObservedObject

一句话区别:

init 的,谁就用 @StateObject
init 的,就用 @ObservedObject

// 正确
struct ParentView: View {
    @StateObject var vm = UserViewModel()
}

// 正确
struct ChildView: View {
    @ObservedObject var vm: UserViewModel
}

❌ 错误用法:

@ObservedObject var vm = UserViewModel() // 会被反复创建

2️⃣ @EnvironmentObject 的本质

不是“魔法全局变量”,而是:

由更高层 View 显式注入的依赖

@main
struct App: App {
    let session = SessionStore()

    var body: some Scene {
        WindowGroup {
            RootView()
                .environmentObject(session)
        }
    }
}
  • View 不负责创建
  • View 假定“环境中一定存在”
  • 缺失会直接 crash(设计使然)

五、一个超级好记的心智模型(推荐)

把它们当成 资源管理声明

@State            = 我有一个小本子
@StateObject      = 我养了一只宠物
@ObservedObject   = 我只是帮别人看宠物
@EnvironmentObject= 社区公共设施

六、错误使用的典型后果(速查)

错误后果
用 @ObservedObject 创建对象View 重建 → 对象重建
用 @StateObject 接收外部对象所有权混乱
滥用 @EnvironmentObject隐式依赖难以维护
用 @State 存引用类型生命周期不可控

最终一句话(压轴版)

SwiftUI 的属性包装器不是“状态类型”,而是“所有权声明”:你在告诉系统——这个状态是谁创建的、谁负责活多久。