Preface
ObservableObject
相比 @State
更自由一些。仅 class
类型可以遵守该协议。视图使用时可以声明为 @ObservedObject
,也可使用 @EnvironmentObject
注入。
实现
先来看下 ObservableObject
的部分代码:
/// A type of object with a publisher that emits before the object has changed.
/// 一种带有发布者的对象类型,其在对象更改之前发出。
///
/// By default an ``ObservableObject`` synthesizes an ``ObservableObject/objectWillChange-2oa5v`` publisher that emits the changed value before any of its `@Published` properties changes.
/// 默认情况下,``ObservableObject`` 合成一个 ``ObservableObject/objectWillChange-2oa5v`` 发布者,其在任何 `Published` 属性更改之前发出更改的值。
///
/// class Contact: ObservableObject {
/// @Published var name: String
/// @Published var age: Int
///
/// init(name: String, age: Int) {
/// self.name = name
/// self.age = age
/// }
///
/// func haveBirthday() -> Int {
/// age += 1
/// return age
/// }
/// }
///
/// let john = Contact(name: "John Appleseed", age: 24)
/// cancellable = john.objectWillChange
/// .sink { _ in
/// print("\(john.age) will change")
/// }
/// print(john.haveBirthday())
/// // Prints "24 will change"
/// // Prints "25"
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ObservableObject : AnyObject {
/// The type of publisher that emits before the object has changed.
associatedtype ObjectWillChangePublisher : Publisher = ObservableObjectPublisher where Self.ObjectWillChangePublisher.Failure == Never
/// A publisher that emits before the object has changed.
var objectWillChange: Self.ObjectWillChangePublisher { get }
}
以其中代码为例:
class Contact: ObservableObject {
@Published var name: String
@Published var age: Int // 2. -> objectWillChange
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1 // 1. 改变 age
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
let cancellable = john.objectWillChange
.sink { _ in
print("\(john.age) will change") // 3. 输出
}
print(john.haveBirthday()) // 4. 打印结果
// Prints "24 will change"
// Prints "25"
而 @Published
的本质是通过 willSet
和 objectWillChange
实现的,也可使用以下方式:
class Contact: ObservableObject {
let objectWillChange = PassthroughSubject<Void, Never>()
var age = 0 {
// 手动在将要设置时调用 send
willSet { // 2.1 willSet 调用
print("age - objectWillChange.send")
// 2.1.1 手动调用 objectWillChange.send
objectWillChange.send()
}
}
var name = "" {
willSet { // 2.2 willSet 调用
print("name - objectWillChange.send")
// 2.2.1 手动调用 objectWillChange.send
objectWillChange.send()
}
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1 // 1. 改变 age
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
let cancellable = john.objectWillChange
.sink { _ in
print("\(john.age) will change") // 3. 输出
}
print(john.haveBirthday()) // 4. 打印结果
// age - objectWillChange.send
// 24 will change
// 25