@ObservedObject
顧名思義來到了最關(guān)鍵的觀察者模式
觀察者模式
當對象間存在一對多關(guān)系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬于行為型模式。
意圖:定義對象間的一種一對多的依賴關(guān)系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。
主要解決:一個對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
何時使用:一個對象(目標對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。
如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。
在 Combine 中,有幾個重要的組成部分:
發(fā)布者:Publiser
訂閱者:Subscriber
操作符:Operator
Publisher
在 Combine 中,Publisher 相當于RxSwift中的 Observable,并且可以通過組合變換(Operator)重新生成新的 Publisher。
public protocol Publisher {
/// The kind of values published by this publisher.
associatedtype Output
/// The kind of errors this publisher might publish.
///
/// Use `Never` if this `Publisher` does not publish errors.
associatedtype Failure : Error
/// This function is called to attach the specified `Subscriber` to this `Publisher` by `subscribe(_:)`
///
/// - SeeAlso: `subscribe(_:)`
/// - Parameters:
/// - subscriber: The subscriber to attach to this `Publisher`.
/// once attached it can begin to receive values.
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
}
Combine提供了一個 enum Publishers,包括:
struct Empty : 一個從不發(fā)布任何值的publisher,并且可以選擇立即完成。
struct Fail : 立即使用指定錯誤終止的publisher。
struct Once: 只有一次向每個訂閱者發(fā)布輸出然后完成的publisher,或者在沒有生成任何元素的情況下立即失敗的publisher。
struct Optional : 如果可選值具有值,則publisher僅向每個訂閱者發(fā)布一次可選值。
struct Sequence : 發(fā)布給定元素序列的publisher。
struct Deferred : 在運行提供的閉包之前等待訂閱的發(fā)布者,以便為新訂閱者創(chuàng)建發(fā)布者
Subscriber
Subscriber相當于RxSwift中的Observer
public protocol Subscriber : CustomCombineIdentifierConvertible {
/// The kind of values this subscriber receives.
associatedtype Input
/// The kind of errors this subscriber might receive.
///
/// Use `Never` if this `Subscriber` cannot receive errors.
associatedtype Failure : Error
/// Tells the subscriber that it has successfully subscribed to the publisher and may request items.
///
/// Use the received `Subscription` to request items from the publisher.
/// - Parameter subscription: A subscription that represents the connection between publisher and subscriber.
func receive(subscription: Subscription)
/// Tells the subscriber that the publisher has produced an element.
///
/// - Parameter input: The published element.
/// - Returns: A `Demand` instance indicating how many more elements the subcriber expects to receive.
func receive(_ input: Self.Input) -> Subscribers.Demand
/// Tells the subscriber that the publisher has completed publishing, either normally or with an error.
///
/// - Parameter completion: A `Completion` case indicating whether publishing completed normally or with an error.
func receive(completion: Subscribers.Completion<Self.Failure>)
}
可以看出,Publisher 在自身狀態(tài)改變時,調(diào)用 Subscriber 的三個不同方法(receive(subscription), receive(_:Input), receive(completion:))來通知 Subscriber。
這里也可以看出,Publisher 發(fā)出的通知有三種類型:
Subscription:Subscriber 成功訂閱的消息,只會發(fā)送一次,取消訂閱會調(diào)用它的 Cancel 方法來釋放資源
Value(Subscriber 的 Input,Publisher 中的 Output):真正的數(shù)據(jù),可能發(fā)送 0 次或多次
Completion:數(shù)據(jù)流終止的消息,包含兩種類型:.finished 和 .failure(Error),最多發(fā)送一次,一旦發(fā)送了終止消息,這個數(shù)據(jù)流就斷開了,當然有的數(shù)據(jù)流可能永遠沒有終止
大部分場景下我們主要關(guān)心的是后兩種消息,即數(shù)據(jù)流的更新和終止。
Combine 內(nèi)置的 Subscriber 有三種:
Sink
Assign
Subject
Sink 是非常通用的 Subscriber,我們可以自由的處理數(shù)據(jù)流的狀態(tài)。
let once: Publishers.Once<Int, Never> = Publishers.Once(100)
let observer: Subscribers.Sink<Int,Never> = Subscribers.Sink(receiveCompletion: {
print("completed: \($0)")
}, receiveValue: {
print("received value: \($0)")
})
once.subscribe(observer)
Assign 可以很方便地將接收到的值通過 KeyPath 設(shè)置到指定的 Class 上(不支持 Struct)
一旦 publisher 的值發(fā)生改變,相應(yīng)的,student 的 score 也會被更新。
PassthroughSubject 這里是 Combine 內(nèi)置的一個 Publisher。
Subject
有些時候我們想隨時在 Publisher 插入值來通知訂閱者,在 Rx 中也提供了一個 Subject 類型來實現(xiàn)。Subject 通常是一個中間代理,即可以作為 Publisher,也可以作為 Subscriber。Subject 的定義如下:
public protocol Subject : AnyObject, Publisher {
/// Sends a value to the subscriber.
///
/// - Parameter value: The value to send.
func send(_ value: Self.Output)
/// Sends a completion signal to the subscriber.
///
/// - Parameter completion: A `Completion` instance which indicates whether publishing has finished normally or failed with an error.
func send(completion: Subscribers.Completion<Self.Failure>)
}
作為 Subscriber 的時候,可以通過 Publisher 的 subscribe(_:Subject) 方法訂閱某個 Publisher。
作為 Publisher 的時候,可以主動通過 Subject 的兩個 send 方法,我們可以在數(shù)據(jù)流中隨時插入數(shù)據(jù)。目前在 Combine 中,有三個已經(jīng)實現(xiàn)對 Subject: AnySubject,CurrentValueSubject 和 PassthroughSubject 。
CurrentValueSubject : 包含單個值并且當值改變時發(fā)布新元素的subject