ReactiveSwift原始碼解析(七) Signal的CombineLatest的程式碼實現
本篇部落格我們就來聊一下combineLatest()的使用以及具體的實現方式。在之前的《》的部落格中我們已經聊過combineLatest()的用法,雖然是使用老版本的ReactiveCocoa和Objective-C語言介紹的,不過使用原理上都是一致的。都是將兩個訊號量進行合併,當其中一個訊號量發出Value事件時,如果另一個訊號量之前也傳送過Value事件,那麼就取出最後一個事件的Value值與當前傳送的事件值進行合併,然後將合併後的值傳送給新的訊號量的觀察者。如果其中一個未傳送過任何Value,那麼將不會向合併後的訊號量的觀察者傳送事件。下方會進行詳細的敘述。
下面我們就來仔細的聊一下combineLatest
一、combineLatest()使用
下方程式碼片段是combineLatest()使用方式,介紹如下:
-
首先建立兩個訊號量,一個是signalString,用來發送Value值為String型別的訊號。另一個是signalInt,用來發送Value值為Int型別的訊號。
-
呼叫訊號量signalString的combineLatest()方法,將signalString訊號量最後傳送的值與訊號量signalInt
-
接著就是呼叫signalString和signalInt所對應的observer物件來發送Value事件了。
從輸出結果我們不難看出,無論是signalString訊號量還是signalInt訊號量發出的Value訊息,只要是另一個訊號量的LastValue不為nil。那麼新的訊號量combineSignal的觀察者就會收到相應的合併後的值,如下具體結果如下所示:
針對上述的示例,我們畫了下方的簡圖來說明合併訊號量的工作方式。Letters
二、combineLatest()的具體程式碼實現
接下來我們就來看一下combineLatest()程式碼的具體實現。下方就是該方法對應的核心程式碼:
-
首先下方這個泛型函式的引數是一個訊號量,而返回值是一個新的訊號量,而這個新的訊號量的型別是一個可以接受元組的訊號量。而這個元組中的兩個值就是這兩個訊號量最後一個值合併而成的。
-
其次建立了一個NSLock型別的鎖,用來保證多執行緒下的原子性操作。
-
定義宣告兩個常量物件,用來儲存兩個合併訊號量最後傳送的值。CombineLatestState<Value>類的實現是比較簡單的,目的就是為了暫存訊號量最後發出的值。
-
然後有定義了一個無參閉包onBothValue, 而這個閉包體中所做的事情是像新生成的合併訊號量傳送合併後的元組訊息。這樣,與新訊號量所關聯的觀察者Observer就會收到這個元組。
-
緊接著就是建立了一個新的代理觀察者observerDelegate, 用來代理新訊號量的Observer來發送各種事件。而這個observerDelegate代理觀察者是代替合併後的新訊號量傳送事件的。
-
最後要做的就是將observerDelegate與要合併的兩個訊號量進行整合關聯,使得要合併的兩個訊號量中的任何一個訊號量發出事件時。在兩者都有LatestValue的情況下,這個新合併的訊號量所繫結的觀察者都可以接收到該事件。
具體程式碼如下所示:
下方這個方法就負責將新的訊號量的傳送事件的Observer與之前訊號量進行整合。具體做法就是往之前的訊號量的Bag容器中新增一個新的觀察者Observer,在這個新的觀察者處理Event事件時,呼叫ObserverDelegate的相關事件即可。
在上述程式碼中,我們對暫存之前兩個訊號量最後發出的值的signalState和otherState進行了相關資訊的列印。先列印了hashValue,然後列印了其暫存的值。當著兩個物件中的latestValue皆不為空時,那麼就呼叫observerDelegate的sendValue方法執行onBothValue閉包,向合併訊號量所有的Observer傳送元組訊息即可。
下方就是對signalState和otherState的相關資訊進行的列印 ,從列印資訊中我們可以看出,儘管在observerWithState()函式中是以引數的形式獲取的signalState和otherState,但是其記憶體地址是不變的,獨一份。而且當這兩個都有lastestValue的情況下,合併訊號量的觀察者才會收到相應的Value事件。具體如下所示。
三、Latest合併原理圖
針對上述的程式碼實現,以及參考之前部落格中原理圖的形式,於是乎我們給出了下方的這個原理圖。原理圖應該是清晰明瞭,一目瞭然的,在此就不做過多的贅述了。通過下圖的結構,我們不難看出,combineLatestSignal訊號量仍然是可以進行鏈式發展的。
在Signal.swift檔案中關於SignalProtocol的擴充套件的方法中,基本上是按照上述的套路來擴充套件的。大體就是一個方法返回一個新的訊號量,這個新的訊號量與原始訊號量間通過橋接訊號量來進行關聯。不同的方法在處理原訊號量往新的訊號量傳送事件時,在中間所做的事情不同。Signal.swift檔案中還有好多類似的方法,在此就不一一進行介紹了,如果你對某個方法的實現感興趣,可以採用上述的套路來進行解析。
今天的部落格就先到這兒,下篇部落格我們會繼續解析ReactiveSwift框架中的其他內容。