ObservableObject 是 SwiftUI 中的一个协议,它用于定义一个可以在视图中被观察的对象。它通常与 @Published 属性包装器一起使用,以便在对象的属性发生变化时,自动更新使用该对象的视图。

  1. ObservableObject 协议

ObservableObject 协议是用于模型(通常是 ViewModel)的类的基类,它通知监听它的视图或其他对象,数据发生了变化。当数据改变时,视图会自动更新以反映这些变化。

主要功能:

•    ObservableObject 协议定义了对象的可观察性,这意味着,当对象的某个属性发生变化时,所有绑定到该对象的视图都会重新渲染。
•    在 SwiftUI 中,通常使用 @ObservedObject 或 @StateObject 来观察一个 ObservableObject 对象。
  1. 如何使用 ObservableObject
  2. 定义一个 ObservableObject 类:

你需要创建一个符合 ObservableObject 协议的类,并在类的属性中使用 @Published 来标记那些需要被观察的属性。

import SwiftUI

class Counter: ObservableObject {

// 使用 @Published 标记属性
@Published var count = 0

func increment() {
    count += 1
}

func decrement() {
    count -= 1
}

}

  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 会自动刷新并显示新的值。

  1. 外部传递 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 对象。

  1. @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 的视图会被通知并更新。

  1. objectWillChange 属性

ObservableObject 协议自动为你提供一个 objectWillChange 发送更新通知的能力。你不需要显式地使用它,SwiftUI 会自动在 @Published 属性更新时触发它。

自定义更新:

如果你希望控制更新的时机,或者想手动发送对象更新通知,可以手动调用 objectWillChange.send():

class MyObject: ObservableObject {

@Published var count = 0

func updateCount() {
    objectWillChange.send()  // 手动触发更新
    count += 1
}

}

  1. 如何避免性能问题

当 ObservableObject 中的某个属性发生变化时,所有依赖它的视图会重新渲染。如果对象的属性发生变化过于频繁,可能会导致性能问题。为了避免这种情况,可以通过减少更新的次数,或者使用 @State 等局部状态来代替 @Published。

  1. 总结
    • ObservableObject 协议用于使类的实例可被视图观察,通常用于数据模型。
    • 使用 @Published 修饰属性,当属性变化时,通知视图更新。
    • 使用 @StateObject 在视图中创建并管理 ObservableObject 实例,使用 @ObservedObject 来观察外部传递的对象。
    • 当对象属性变化时,视图会自动更新以反映这些变化。
最后修改:2024 年 12 月 20 日
如果觉得我的文章对你有用,请随意赞赏