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 传递

本质

@StateView 的本地状态缓存,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 不是在问"用哪个",而是在问:

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

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

相关推荐
神奇的程序员1 天前
开发了一个进阶版Apple健康
swiftui·apple·apple watch
东坡肘子3 天前
Swift 还让你 Excited 吗?-- 肘子的 Swift 周报 #141
人工智能·swiftui·swift
壹方秘境4 天前
我用Go语言开发了一个跨平台的HTTPS抓包和调试工具
前端·后端·ios
sweet丶6 天前
Swift 元编程-Macro
swift
初级代码游戏9 天前
easy Photo Clean公测版:快速清理iPhone照片 邀请公测
ios·iphone
库奇噜啦呼9 天前
【iOS】RunLoop学习
学习·ios
影寂ldy9 天前
WinForm PictureBox控件 + ImageList组件 完整笔记
开发语言·笔记·swift
黑科技iOS上架9 天前
iOS应用周末提交什么情况算卡审
经验分享·ios
zzb15809 天前
ios基础-MVC-UIView
ios·mvc·cocoa