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 不是在问"用哪个",而是在问:

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

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

相关推荐
SameX7 小时前
独立开发了一款健康记录 App,聊聊几个让我纠结很久的设计决策
ios
报错小能手8 小时前
Swift UI 框架 实战 简易计数器、待办清单 、随机壁纸图库、个人笔记
ui·ios
游戏开发爱好者89 小时前
深入理解iOSTime Profiler:提升iOS应用性能的关键工具
android·ios·小程序·https·uni-app·iphone·webview
for_ever_love__1 天前
UI学习:多界面传值的正向传值(属性传值)和反向传值(代理传值)
学习·ui·ios·objective-c
开心就好20251 天前
全面介绍iOS开发工具:Xcode、AppCode、CocoaPods、Fastlane和Git
后端·ios
懋学的前端攻城狮1 天前
数据持久化与缓存策略:在离线与在线间架起桥梁
ios·swift
~央千澈~1 天前
以cocos3.8.8开发的游戏为例商业实战项目举例cocos打包ios苹果安装包ipa完整详细教程-优雅草卓伊凡
ios
SameX1 天前
iOS 足迹 App 的成就系统,我推倒重做了一次——踩了3个坑之后
ios
SameX1 天前
我做了一个把专注计时变成「声音护照」的 iOS App,聊聊数据可视化和成长系统的设计思路
ios