一個(gè)信號(hào)發(fā)生器,由
SignalProducer
類(lèi)型表示,可以創(chuàng)建信號(hào)(signals
)并施加副作用(side effects
)。
信號(hào)發(fā)生器用來(lái)表示操作或者任務(wù),比如網(wǎng)絡(luò)請(qǐng)求,每一次對(duì)它調(diào)用
start()
將會(huì)生成一個(gè)新的后臺(tái)操作,并允許調(diào)用者監(jiān)視它的結(jié)果。另一種形式的startWithSignal()
方法,會(huì)給出產(chǎn)生的信號(hào),允許在必要的情況下被監(jiān)聽(tīng)多次。
根據(jù)
start()
方法的動(dòng)作方式,被同一個(gè)信號(hào)發(fā)生器生成的信號(hào)可能會(huì)有不同的事件順序或版本,甚至事件流完全不一樣!和普通的信號(hào)不同,在監(jiān)聽(tīng)器連接上之前,信號(hào)發(fā)生器不會(huì)開(kāi)始工作(也就沒(méi)有事件會(huì)生成),并且在每一個(gè)新的監(jiān)聽(tīng)器連接上時(shí)其工作都會(huì)重新開(kāi)始。
啟動(dòng)一個(gè)信號(hào)發(fā)生器會(huì)返回一個(gè)存根(
disposable
),它可用來(lái)打斷或取消被生成信號(hào)的工作。
和信號(hào)一樣,信號(hào)生成器可以通過(guò)
map
、filter
等原函數(shù)操作。使用lift
方法,所有信號(hào)的原函數(shù)可以被提升成為以信號(hào)生成器為對(duì)象的操作。除此以外,還有一些用來(lái)控制何時(shí)與如何啟動(dòng)信號(hào)生成器的原函數(shù),比如times
。
1. 信號(hào)發(fā)生器什么樣
簡(jiǎn)單地講,信號(hào)發(fā)生器就是一個(gè)制造信號(hào)的方法。在信號(hào)發(fā)生器內(nèi)部,這個(gè)方法稱(chēng)為啟動(dòng)處理器(startHandler),它是信號(hào)發(fā)生器僅有的數(shù)據(jù)成員:
public struct SignalProducer<Value, Error: ErrorType> {
public typealias ProducedSignal = Signal<Value, Error>
private let startHandler: (Signal<Value, Error>.Observer, CompositeDisposable) -> ()
......
}
也就是說(shuō),信號(hào)發(fā)生器看起來(lái)是這樣的:
2. 創(chuàng)建信號(hào)發(fā)生器
信號(hào)發(fā)生器的初始化函數(shù)同樣十分簡(jiǎn)單,就是將我們提供的參數(shù)作為啟動(dòng)處理器保存起來(lái):
public struct SignalProducer<Value, Error: ErrorType> {
......
public init(_ startHandler: (Signal<Value, Error>.Observer, CompositeDisposable) -> ()) {
self.startHandler = startHandler
}
......
}
為了更順利地討論后面的內(nèi)容,我們?cè)诖思s定:信號(hào)發(fā)生器制造出來(lái)的信號(hào)稱(chēng)為結(jié)果信號(hào)(produced signal)。
現(xiàn)在要看看我們的任務(wù)了:定義啟動(dòng)處理器。啟動(dòng)處理器的主要內(nèi)容,就是定義結(jié)果信號(hào)的事件源。它會(huì)在信號(hào)發(fā)生器每次啟動(dòng)時(shí)被調(diào)用,也就是說(shuō),結(jié)果信號(hào)只有在信號(hào)發(fā)生器啟動(dòng)時(shí)才會(huì)生成,而且每一次啟動(dòng)信號(hào)生成器都會(huì)得到一個(gè)新的結(jié)果信號(hào),只不過(guò)這些結(jié)果信號(hào)的事件源工作方式相同(但產(chǎn)生的事件不一定相同)。
啟動(dòng)處理器是一個(gè)簽名為(Observer, CompositeDisposable) -> ()
的方法,第一個(gè)參數(shù)就是結(jié)果信號(hào)(即將被制造的信號(hào))的事件分發(fā)器,如果我們向這個(gè)分發(fā)器發(fā)送事件的話(huà),結(jié)果信號(hào)的監(jiān)聽(tīng)器就會(huì)收到。
3. 啟動(dòng)信號(hào)發(fā)生器
啟動(dòng)信號(hào)發(fā)生器,可以調(diào)用信號(hào)發(fā)生器對(duì)象的startWithSignal(setUp: (Signal, Disposable) -> ())
方法,這個(gè)方法接收一個(gè)回調(diào)函數(shù)作為參數(shù),而我們必須提供這個(gè)回調(diào)函數(shù)。正如參數(shù)名稱(chēng)setUp所暗示的,這個(gè)回調(diào)函數(shù)會(huì)在信號(hào)的事件源開(kāi)始工作(也就是發(fā)送事件)之前執(zhí)行,信號(hào)的引用和一個(gè)取消用存根被交到我們手中,這給了我們一個(gè)機(jī)會(huì)做一些準(zhǔn)備工作,比如向信號(hào)添加監(jiān)聽(tīng)器,將信號(hào)變形,或者干脆通過(guò)取消用存根取消啟動(dòng)等等。
下面是startWithSignal執(zhí)行的步驟:
- 調(diào)用Signal類(lèi)的pipe()類(lèi)方法,得到一個(gè)信號(hào)和這個(gè)信號(hào)的事件分發(fā)器。
- 創(chuàng)建一個(gè)CompositeDisposable類(lèi)型的發(fā)生器存根。
- 創(chuàng)建一個(gè)ActionDisposable類(lèi)型的取消用存根,如果這個(gè)存根被廢棄,它會(huì)在事件分發(fā)器上發(fā)送一個(gè)Interrupted事件,之后將上一步中創(chuàng)建的發(fā)生器存根廢棄掉。
- 將信號(hào)和取消用存根交給回調(diào)方法setUp,執(zhí)行我們的準(zhǔn)備工作。
- 如果準(zhǔn)備工作后取消用存根被廢棄了,就停止處理立即返回。
- 將信號(hào)的事件分發(fā)器包裝在一個(gè)監(jiān)聽(tīng)器對(duì)象(wrapperObserver)中,這個(gè)監(jiān)聽(tīng)器對(duì)象會(huì)將自己接收到的所有事件原封不動(dòng)地交給事件分發(fā)器,不過(guò)一旦它接收到終結(jié)事件,它會(huì)廢棄第二步中創(chuàng)建的生成器存根。
- 使用上一步包裝過(guò)的監(jiān)聽(tīng)器和第二步中創(chuàng)建的發(fā)生器存根調(diào)用啟動(dòng)處理器。
4. 緩沖(Buffer)
緩沖,由
SignalProducer.buffer()
方法創(chuàng)建,是一個(gè)事件的隊(duì)列(queue),每當(dāng)信號(hào)發(fā)生器創(chuàng)建新的信號(hào)時(shí),隊(duì)列中的事件會(huì)被重播(replay)。
和管道(
pipe
)相似,這個(gè)方法返回一個(gè)監(jiān)聽(tīng)器(Observer)。向這個(gè)監(jiān)聽(tīng)器發(fā)送的事件會(huì)被加入隊(duì)列中。如果在加入新的事件時(shí),隊(duì)列已經(jīng)達(dá)到最大容量(隊(duì)列長(zhǎng)度),那么為了以騰出空間,隊(duì)列中最早加入的事件會(huì)被移除。