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

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

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

相关推荐
AIsoft_86887 小时前
iPhone录音重点标记:会议录音与重点内容同步保存功能实测
ios·iphone
00后程序员张7 小时前
使用Instruments工具深入分析iOS应用性能与启动时间优化
android·macos·ios·小程序·uni-app·cocoa·iphone
90后的晨仔9 小时前
Xcode 26.6编译 AFNetworking 报错全解:5 种方案从应急到根治
ios
初级代码游戏1 天前
iOS开发 Swift 速记1:变量和基本数据类型
开发语言·ios·swift
for_ever_love__1 天前
iOS:网络请求再学习
网络·学习·ios·objective-c
大龄秃头程序员1 天前
Swift 值类型真的每次都会拷贝吗?OC 老兵聊聊 COW
swift
2501_915921431 天前
SwiftUI开发框架入门指南:从基础到实战
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_916007471 天前
Python实现HTTPS爬虫的完整指南:使用requests、BeautifulSoup、Selenium和Scrapy
爬虫·python·ios·小程序·https·uni-app·iphone
LDyun_1 天前
云手机低延迟怎么实现的?为什么云手机能够 7×24 小时在线?
ios·智能手机·安卓·玩游戏
for_ever_love__1 天前
iOS: 网络请求第三方库的使用: AFNetworking
网络·学习·ios·objective-c·cocoa·xcode