SwiftUI 最新数据模型完整解析:@Observable、@State、@Bindable(iOS17+ 全新范式)

自 iOS 17 起,SwiftUI 引入了 全新的 Observation 模型

它用三个核心工具彻底重塑了数据管理方式:

  • @Observable ------ 定义可观察的状态模型

  • @State ------ 持有模型实例,等价于旧时代的 @StateObject

  • @Bindable ------ 在视图中实现对 Observable 模型的双向绑定

如果你还在用 ObservableObject、@Published、@StateObject、@ObservedObject、@EnvironmentObject,是时候升级了:新范式更简单、更 Swift、更高性能。

本文将系统梳理 SwiftUI 最新的数据管理体系。


🧱 一、旧数据体系的问题

iOS 16 及以前,我们管理状态基本依赖:

  • ObservableObject

  • @Published

  • @StateObject

  • @ObservedObject

  • @EnvironmentObject

这些机制的问题:

  • 装饰器太多,容易混乱

  • 生命周期容易搞错(尤其是 @StateObject vs @ObservedObject)

  • @Published 对属性执行全局广播,性能不够优雅

  • 环境写法不够类型安全

新模型的目标:让 SwiftUI 更简单、更自动、更智能。


🚀 二、@Observable:新时代核心

新系统中的任何可观察模型,只要声明:

swift 复制代码
@Observable
class UserModel {
    var name = "HanQiu"
    var age = 23
}

不再需要:

  • ObservableObject

  • @Published

  • 手动发布变更

所有存储属性都是可观察的,SwiftUI 会精确追踪变化来源。


🧩 三、@State取代@StateObject

在旧时代,创建页面级别持久的模型需要:

swift 复制代码
@StateObject var vm = UserModel()

在新系统中:

swift 复制代码
@State var vm = UserModel()

是的, @State 自动完成以前 @StateObject 的作用

  • 保持引用类型实例生命周期

  • 在视图重建中保持稳定

  • 触发视图刷新

只要你的模型是 @Observable 的,就可以用 @State 持有。


🧠 四、那@ObservedObject呢?------ 不需要了

旧写法(子视图):

swift 复制代码
struct ProfileView: View {
    @ObservedObject var vm: UserModel
}

新写法:

swift 复制代码
struct ProfileView: View {
    var vm: UserModel
}

SwiftUI 会自动观察视图中"被使用的属性"。

你不需要告诉它"这个对象可观察",它本身就知道(因为模型是 @Observable)。


🌿 五、环境注入方式的升级

旧写法:

swift 复制代码
@EnvironmentObject var settings: SettingsModel

新写法更强、更明确:

注入

swift 复制代码
struct AppRoot: View {
    @State var settings = SettingsModel()

    var body: some View {
        MainView()
            .environment(settings)
    }
}

获取

swift 复制代码
@Environment(SettingsModel.self) var settings

减少误用,也更符合 Swift 语言本身的表达。


⭐ 六、重点:@Bindable的出现解决了什么?

@Observable 模型虽然自动可观察,但 UI 控件(如 TextField)需要 双向绑定

swift 复制代码
TextField("Name", text: $vm.name)

新模型中,属性只是普通 stored property,不是 Published,不具备 Binding 能力。

于是 Swift 引入:

✔@Bindable

为 View 提供 绑定视角的模型访问


🧲 七、@Bindable的标准用法

模型

swift 复制代码
@Observable
class UserModel {
    var name = ""
    var age = 18
}

视图(可编辑 UI)

swift 复制代码
struct EditUserView: View {
    @Bindable var user: UserModel

    var body: some View {
        Form {
            TextField("Name", text: $user.name)
            Stepper("Age: \(user.age)", value: $user.age)
        }
    }
}

只需标记 @Bindable,模型属性即可自动得到 $binding。


🧩 八、为什么不是所有时候都用@Bindable?

是否需要取决于:

情况 是否需要 @Bindable
仅用于展示,不会修改模型 ❌ No
需要用 TextField / Toggle / Stepper 修改模型 ✔ Yes
子视图要修改父模型 ✔ Yes
完全只读视图 ❌ No

越"表单"风格的页面,越需要 @Bindable。


🚦 九、@Bindable的局部绑定写法(推荐技巧)

你也可以只在 body 内使用 Bindable:

swift 复制代码
var body: some View {
    @Bindable var b = user   // 局部绑定

    VStack {
        TextField("Name", text: $b.name)
        Stepper("Age: \(b.age)", value: $b.age)
    }
}

不会污染结构体属性定义,适合仅局部可编辑的 UI。


🧭 十、三者关系总结(最重要)

less 复制代码
@Observable   ------ 使模型可观察
@State        ------ 在 View 中持有模型(生命周期 = 旧 @StateObject)
@Bindable     ------ 提供绑定能力,允许 UI 修改模型

一个"完整数据流"的表达式:

@Observable 定义状态 → @State 持有 → @Bindable 编辑 → SwiftUI 自动刷新


🧪 十一、完整示例:新 Paradigm 最佳实践

swift 复制代码
@Observable
class ProfileModel {
    var name = "HanQiu"
    var level = 1
}

struct ProfileView: View {
    @State var profile = ProfileModel()

    var body: some View {
        VStack {
            Text("Name: \(profile.name)")
            Text("Level: \(profile.level)")

            EditSection(profile: profile)
        }
    }
}

struct EditSection: View {
    @Bindable var profile: ProfileModel

    var body: some View {
        VStack {
            TextField("Name", text: $profile.name)
            Stepper("Level: \(profile.level)", value: $profile.level)
        }
        .padding()
    }
}

无需 @Published,不用 @StateObject,不需要 @ObservedObject。

SwiftUI 的数据管理彻底简化。


🧾 十二、迁移指南(旧 → 新)

旧 API 新 API
ObservableObject @Observable
@Published 不需要
@StateObject @State
@ObservedObject 删除,直接传模型
@EnvironmentObject .environment(model) + @Environment(Model.self)
双向绑定属性 使用 @Bindable

🎉 总结

SwiftUI 从 iOS17 开始进入 Observation 时代

  • @Observable → 自动观察

  • @State → 管理模型生命周期

  • @Bindable → 构建表单/编辑 UI 的关键

  • 更少的装饰器

  • 更精准的性能优化

  • 更符合 Swift 语言设计哲学

如果你写 SwiftUI,这套新范式未来几年都会是主流。


相关推荐
大熊猫侯佩7 小时前
Swift 6.2 列传(第十三篇):香香公主的“倾城之恋”与优先级飞升
swift·编程语言·apple
1024小神14 小时前
Swift配置WKwebview加载网站或静态资源后,开启调试在电脑上debug
swift
guangzan18 小时前
AI 结对编程:如何让 AI 跳出死循环?
swiftui·vibe coding
kkoral2 天前
基于MS-Swift 为 Qwen3-0.6B-Base 模型搭建可直接调用的 API 服务
python·conda·fastapi·swift
Yorelee.3 天前
ms-swift在训练时遇到的部分问题及解决方案
开发语言·nlp·transformer·swift
崽崽长肉肉3 天前
swift中的知识总结(一)
ios·swift
Yakamoz4 天前
Swift Array的写时复制
swift
汉秋4 天前
SwiftUI 中的 compositingGroup():真正含义与渲染原理
swiftui·swift
汉秋4 天前
SwiftUI 中的 @ViewBuilder 全面解析
swiftui·swift
胖虎14 天前
SwiftUI 页面作为一级页面数据被重置问题分析
ios·swiftui·swift·state·observedobject·stateobject·swiftui页面生命周期