Combine之Subjects
在響應(yīng)式編程的世界中儡炼,Subject不太好翻譯响牛。在Combine中玷禽,存在兩個Subjects,本質(zhì)上娃善,他們就是一種特殊的publisher论衍。之所以稱他們是特殊的瑞佩,是因為他們不僅包含publisher通用的一些特性聚磺,還具有獨特的地方,接下來炬丸,我們逐個解釋瘫寝。
先看看Subject的定義:
/// A publisher that exposes a method for outside callers to publish elements.
///
/// A subject is a publisher that you can use to ”inject” values into a stream, by calling its ``Subject/send(_:)`` method. This can be useful for adapting existing imperative code to the Combine model.
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
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>)
/// Sends a subscription to the subscriber.
///
/// This call provides the ``Subject`` an opportunity to establish demand for any new upstream subscriptions.
///
/// - Parameter subscription: The subscription instance through which the subscriber can request elements.
func send(subscription: Subscription)
}
復(fù)制代碼
通過上邊的代碼可以看出,Subject
本身就是一個協(xié)議稠炬,因為它繼承了Publisher
協(xié)議焕阿,所以才說它是一種特殊的Publisher
。它最核心的內(nèi)容是提供了3個send
方法:
-
func send(_ value: Self.Output)
該方法可以讓我們在任何時候任何地方發(fā)送任何數(shù)據(jù)首启,這提供了非常靈活的數(shù)據(jù)發(fā)送能力暮屡。 -
func send(completion: Subscribers.Completion<Self.Failure>)
該方法可以讓我們發(fā)送.finished
或者.failure
事件,用于結(jié)束該pipline毅桃。 -
func send(subscription: Subscription)
該方法發(fā)送一個subscription給訂閱者褒纲,建議兩者溝通的一個中間渠道准夷。
總之一句話,send
是Subject
的核心方法莺掠,也是核心理念衫嵌。
CurrentValueSubject
[圖片上傳中...(image-78de00-1611882474037-2)]
CurrentValueSubject
最特殊的地方有2點:
- 它有一個初始值,也可以稱之為最開始它當(dāng)前的值就是它的初始值
- 當(dāng)調(diào)用
send
發(fā)送新的數(shù)據(jù)的時候彻秆,它更新當(dāng)前的值楔绞,然后發(fā)送給訂閱者
其中,最有意思的一點是唇兑,當(dāng)它再次收到一個新的訂閱的情況下酒朵,它會給新的訂閱著發(fā)送它當(dāng)前的值:
[圖片上傳中...(image-77b814-1611882474037-1)]
總之一句話,CurrentValueSubject是有記憶的幔亥。
let publisher = CurrentValueSubject<Int, Never>(5)
cancellable1 = publisher
.sink(receiveValue: { print($0) })
publisher.send(1)
publisher.send(2)
publisher.send(3)
cancellable2 = publisher
.sink(receiveValue: { print($0) })
復(fù)制代碼
PassthroughSubject
[圖片上傳中...(image-11d8-1611882474037-0)]
如果大家理解了上邊講解的CurrentValueSubject
,那么就很好理解PassthroughSuject
了耻讽,它更加簡單直接,它不記憶任何狀態(tài)帕棉,只傳遞數(shù)據(jù)针肥。
這里要說的一點是,PassthroughSubject
是一個比較常用的publisher香伴,尤其用于test慰枕,主要原因是,它能夠讓我們自由控制數(shù)據(jù)的發(fā)送時機(jī)即纲。