在 Swift 中,@Observable 是 Swift 语言最近引入的一个属性包装器,用来简化状态管理和数据绑定。它的主要作用是让数据在发生变化时可以自动通知到观察它的视图,使界面自动更新。@Observable 主要与 SwiftUI 一起使用,可以让我们更轻松地管理视图状态。
主要特点
自动更新:标记为 @Observable 的类属性在发生变化时会通知到相关的 SwiftUI 视图,触发界面的自动刷新。
简洁:相比其他状态管理方式(如 @Published + @StateObject),@Observable 提供了一个更简洁的方案,减少了样板代码。
多属性观察:@Observable 允许在同一个类中管理多个属性的变化。
基本使用
要使用 @Observable,可以在 Swift 类中标记需要观察的属性:
import SwiftUI
import Observation
@Observable
class MyModel {
var name: String = ""
var age: Int = 0
}
然后在 SwiftUI 的视图中,可以直接使用这个 @Observable 标记的对象:
struct ContentView: View {
@State private var model = MyModel()
var body: some View {
VStack {
Text("Name: \(model.name)")
Text("Age: \(model.age)")
Button("Increase Age") {
model.age += 1
}
}
}
}
在这里,@Observable 使得 model 中的 name 和 age 的更改自动刷新 ContentView 的界面。
什么时候使用 @Observable
需要自动刷新 UI:当对象属性改变时,UI 需要自动响应更新。
简化代码:希望简化数据模型的属性定义,不用逐个加 @Published。
与 @Published 的区别
自动通知:@Observable 是一个较新的机制,它直接标记整个类,而 @Published 是一个属性包装器,必须逐个属性声明。
简洁性:@Observable 去除了手动声明 @StateObject 或 @ObservedObject 的需要,减少了额外的代码。
和@State使用
在 SwiftUI 中,@Observable 类型可以与 @State 一起使用,而不是 @StateObject,因为 @Observable 采用了 Swift 5.9 的新数据管理机制,并与 SwiftUI 更深层次地集成。这使得 SwiftUI 可以直接通过 @State 观察 @Observable 类型的对象。
具体原因
1、@Observable 的设计:
@Observable 是 Swift 5.9 引入的特性,提供了一种新的数据观察模型,不再依赖 ObservableObject 和 @Published。
@Observable 自动为类的属性提供了更新通知,而不需要实现 ObservableObject 协议。
2、@State 的支持:
@State 是专门为 SwiftUI 的视图状态设计的,SwiftUI 能够识别 @State 标记的 @Observable 对象并自动响应其更改。
因此,不需要额外使用 @StateObject 来创建一个外部对象的引用,@State 就可以支持 @Observable 对象的变化和管理生命周期。
3、为什么不是 @StateObject:
@StateObject 是用来管理符合 ObservableObject 协议的外部引用的生命周期,适合较重的对象(比如需要复杂的数据处理或依赖注入的模型对象)。
@Observable 对象已经具备了状态观察的功能,因此只需要 @State 来触发 SwiftUI 的自动更新。
示例
@Observable
class MyModel {
var name: String = "Alice"
var age: Int = 25
}
struct ContentView: View {
@State private var model = MyModel() // @State 直接用于管理 @Observable 对象
var body: some View {
VStack {
Text("Name: \(model.name)")
Text("Age: \(model.age)")
Button("Increase Age") {
model.age += 1
}
}
}
}
使用 @State 是因为 @Observable 类型已经实现了观察和更新,而 @StateObject 主要用于管理 ObservableObject 类型对象的生命周期。
SwiftUI 可以直接观察 @Observable 对象中的属性变化,从而自动刷新视图。
ObservableObject和@Observable区别和关联
在使用 @Observable 的时候,不需要声明 ObservableObject。这是因为 @Observable 是 Swift 的新特性,它实现了与 ObservableObject 类似的功能,但更加简洁和自动化。
1、无需继承:
@Observable 直接作用于类,不需要继承 ObservableObject。这是因为它自动提供了观察者通知机制,无需额外实现 objectWillChange 或使用 @Published。
ObservableObject 是 SwiftUI 之前用来声明和管理可观察对象的协议。在使用 ObservableObject 时,我们通常需要用 @Published 标记每一个需要观察的属性,这样才能在属性发生变化时通知视图进行更新。
2、属性声明更简单:
使用 @Observable,只需将整个类声明为可观察对象,类中的每个属性都会自动通知视图更新。
使用 ObservableObject,则需要手动使用 @Published 来标记每一个可观察的属性。
3、Swift 语言层面的更新:
@Observable 是 Swift 新的 Observation 框架的一部分,是语言层面的更原生的特性,比 ObservableObject 的实现更加直接。
ObservableObject 是一个 SwiftUI 框架的协议,而 @Observable 则在语言层面更紧密地结合到 Swift 本身中。
4、替代关系:
@Observable 的引入使得某些情况下可以替代 ObservableObject,特别是在使用 SwiftUI 时,它可以减少很多样板代码。然而,ObservableObject 仍然存在并兼容于现有的 SwiftUI 代码,所以如果项目中已经使用了 ObservableObject,它不需要立即迁移。
代码对比
使用 ObservableObject 和 @Published 时:
import SwiftUI
class MyModel: ObservableObject {
@Published var name: String = ""
@Published var age: Int = 0
}
struct ContentView: View {
@StateObject private var model = MyModel()
var body: some View {
VStack {
Text("Name: \(model.name)")
Text("Age: \(model.age)")
Button("Increase Age") {
model.age += 1
}
}
}
}
使用 @Observable 时则更简单:
import SwiftUI
import Observation
@Observable
class MyModel {
var name: String = ""
var age: Int = 0
}
struct ContentView: View {
@State private var model = MyModel()
var body: some View {
VStack {
Text("Name: \(model.name)")
Text("Age: \(model.age)")
Button("Increase Age") {
model.age += 1
}
}
}
}
@Observable 是更简化的方案,直接为整个类提供观察支持,不再需要 ObservableObject 或 @Published。
它是 Swift 新的 Observation 框架的一部分,旨在简化代码和增强性能。
在新代码中,@Observable 可以优先使用,而 ObservableObject 仍然兼容现有代码。
总结
@Observable 提供了 Swift 和 SwiftUI 一体化的状态管理方式,更加简洁、自动化,适合用于简化界面与数据模型之间的同步工作。