3

Swift 中的 ObservableObject

 1 year ago
source link: https://kingcos.me/posts/2022/swift_observable_object/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Release Notes ↕

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 的本质是通过 willSetobjectWillChange 实现的,也可使用以下方式:

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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK