ObservableObject 是 SwiftUI 中的一个协议,它用于定义一个可以在视图中被观察的对象。它通常与 @Published 属性包装器一起使用,以便在对象的属性发生变化时,自动更新使用该对象的视图。
- ObservableObject 协议
ObservableObject 协议是用于模型(通常是 ViewModel)的类的基类,它通知监听它的视图或其他对象,数据发生了变化。当数据改变时,视图会自动更新以反映这些变化。
主要功能:
• ObservableObject 协议定义了对象的可观察性,这意味着,当对象的某个属性发生变化时,所有绑定到该对象的视图都会重新渲染。
• 在 SwiftUI 中,通常使用 @ObservedObject 或 @StateObject 来观察一个 ObservableObject 对象。
- 如何使用 ObservableObject
- 定义一个 ObservableObject 类:
你需要创建一个符合 ObservableObject 协议的类,并在类的属性中使用 @Published 来标记那些需要被观察的属性。
import SwiftUI
class Counter: ObservableObject {
// 使用 @Published 标记属性
@Published var count = 0
func increment() {
count += 1
}
func decrement() {
count -= 1
}
}
- 在视图中使用 @ObservedObject 或 @StateObject 来观察对象:
• @StateObject:用于视图内创建和管理 ObservableObject 实例,它会在视图生命周期内保持对象的状态。
• @ObservedObject:用于视图内观察外部传递的 ObservableObject 实例,通常是通过依赖注入的方式传递。
示例:
struct CounterView: View {
// 使用 @StateObject 来管理对象的生命周期
@StateObject private var counter = Counter()
var body: some View {
VStack {
Text("Count: \(counter.count)")
.font(.largeTitle)
HStack {
Button("Increment") {
counter.increment()
}
.padding()
Button("Decrement") {
counter.decrement()
}
.padding()
}
}
.padding()
}
}
在上面的代码中,CounterView 创建了一个 Counter 对象并观察它。当 Counter 中的 count 属性变化时,CounterView 会自动刷新并显示新的值。
- 外部传递 ObservableObject 示例:
如果你需要从外部传递一个已经创建的 ObservableObject 实例,你应该使用 @ObservedObject。
struct ParentView: View {
@StateObject private var counter = Counter()
var body: some View {
ChildView(counter: counter) // 通过构造函数将 counter 传递给子视图
}
}
struct ChildView: View {
@ObservedObject var counter: Counter
var body: some View {
VStack {
Text("Count: \(counter.count)")
.font(.largeTitle)
Button("Increment") {
counter.increment()
}
.padding()
}
}
}
在上面的例子中,ParentView 使用 @StateObject 创建并管理 Counter 实例,而 ChildView 使用 @ObservedObject 来观察传递给它的 counter 对象。
- @Published 属性包装器
@Published 是用于标记在 ObservableObject 类中某个属性需要被观察的属性包装器。当这些属性的值发生变化时,它会通知所有观察这个对象的视图重新渲染。
示例:
class UserSettings: ObservableObject {
@Published var username: String
@Published var isDarkMode: Bool
init(username: String, isDarkMode: Bool) {
self.username = username
self.isDarkMode = isDarkMode
}
}
在这个例子中,username 和 isDarkMode 都是 @Published,当它们的值变化时,所有观察 UserSettings 的视图会被通知并更新。
- objectWillChange 属性
ObservableObject 协议自动为你提供一个 objectWillChange 发送更新通知的能力。你不需要显式地使用它,SwiftUI 会自动在 @Published 属性更新时触发它。
自定义更新:
如果你希望控制更新的时机,或者想手动发送对象更新通知,可以手动调用 objectWillChange.send():
class MyObject: ObservableObject {
@Published var count = 0
func updateCount() {
objectWillChange.send() // 手动触发更新
count += 1
}
}
- 如何避免性能问题
当 ObservableObject 中的某个属性发生变化时,所有依赖它的视图会重新渲染。如果对象的属性发生变化过于频繁,可能会导致性能问题。为了避免这种情况,可以通过减少更新的次数,或者使用 @State 等局部状态来代替 @Published。
- 总结
• ObservableObject 协议用于使类的实例可被视图观察,通常用于数据模型。
• 使用 @Published 修饰属性,当属性变化时,通知视图更新。
• 使用 @StateObject 在视图中创建并管理 ObservableObject 实例,使用 @ObservedObject 来观察外部传递的对象。
• 当对象属性变化时,视图会自动更新以反映这些变化。