ReactiveSwift源碼解析(七) Signal的CombineLatest的代碼實現

本篇博客咱們就來聊一下combineLatest()的使用以及具體的實現方式。在以前的《iOS開發之ReactiveCocoa下的MVVM》的博客中咱們已經聊過combineLatest()的用法,雖然是使用老版本的ReactiveCocoaObjective-C語言介紹的,不過使用原理上都是一致的。都是將兩個信號量進行合併,當其中一個信號量發出Value事件時,若是另外一個信號量以前也發送過Value事件,那麼就取出最後一個事件的Value值與當前發送的事件值進行合併,而後將合併後的值發送給新的信號量的觀察者。若是其中一個未發送過任何Value,那麼將不會向合併後的信號量的觀察者發送事件。下方會進行詳細的敘述。html

下面咱們就來仔細的聊一下combineLatest()的使用方式、具體的代碼實現以及合併信號量的工做原理。下方的使用示例咱們仍是與《iOS開發之ReactiveCocoa下的MVVM》這篇博客中聊combineLatest()時使用是示例相同,只不過咱們是使用的Swift語言寫的,詳情以下。git

 

1、combineLatest()使用github

下方代碼片斷是combineLatest()使用方式,介紹以下:swift

  • 首先建立兩個信號量,一個是 signalString,用來發送Value值爲String類型的信號。另外一個是 signalInt,用來發送Value值爲Int類型的信號。
  • 調用信號量 signalString的combineLatest()方法,將signalString信號量最後發送的值與信號量 signalInt最後發送的值進行合併。而後將合併後的元組(String, Int)發送給新建立的combineLatestSignal信號量的全部觀察者。
  • 接着就是調用 signalStringsignalInt所對應的 observer對象來發送Value事件了。

從輸出結果咱們不難看出,不管是signalString信號量仍是signalInt信號量發出的Value消息,只要是另外一個信號量的LastValue不爲nil。那麼新的信號量combineSignal的觀察者就會收到相應的合併後的值,以下具體結果以下所示:多線程

  

 

針對上述的示例,咱們畫了下方的簡圖來講明合併信號量的工做方式。LettersNumber是兩個信號量,Combine是二者經過combineLatest()方法生成的新的信號量,而後LettersNumber信號量就隨機發送消息。Combine信號量根據LetterNumbers發送值的狀況進行信號量的輸出。具體以下所示。閉包

  

 

 

2、combineLatest()的具體代碼實現框架

接下來咱們就來看一下combineLatest()代碼的具體實現。下方就是該方法對應的核心代碼:函數

  • 首先下方這個泛型函數的參數是一個信號量,而返回值是一個新的信號量,而這個新的信號量的類型是一個能夠接受元組的信號量。而這個元組中的兩個值就是這兩個信號量最後一個值合併而成的。
  • 其次建立了一個 NSLock類型的鎖,用來保證多線程下的原子性操做。
  • 定義聲明兩個常量對象,用來存儲兩個合併信號量最後發送的值。 CombineLatestState<Value>類的實現是比較簡單的,目的就是爲了暫存信號量最後發出的值。
  • 而後有定義了一個無參閉包 onBothValue, 而這個閉包體中所作的事情是像新生成的合併信號量發送合併後的元組消息。這樣,與新信號量所關聯的觀察者Observer就會收到這個元組。
  • 緊接着就是建立了一個新的代理觀察者observerDelegate, 用來代理新信號量的 Observer來發送各類事件。而這個 observerDelegate代理觀察者是代替合併後的新信號量發送事件的。
  • 最後要作的就是將 observerDelegate與要合併的兩個信號量進行整合關聯,使得要合併的兩個信號量中的任何一個信號量發出事件時。在二者都有 LatestValue的狀況下,這個新合併的信號量所綁定的觀察者均可以接收到該事件。

具體代碼以下所示:post

  

 

下方這個方法就負責將新的信號量的發送事件的Observer與以前信號量進行整合。具體作法就是往以前的信號量的Bag容器中添加一個新的觀察者Observer,在這個新的觀察者處理Event事件時,調用ObserverDelegate的相關事件便可。url

  

 

在上述代碼中,咱們對暫存以前兩個信號量最後發出的值的signalStateotherState進行了相關信息的打印。先打印了hashValue,而後打印了其暫存的值。當着兩個對象中的latestValue皆不爲空時,那麼就調用observerDelegatesendValue方法執行onBothValue閉包,向合併信號量全部的Observer發送元組消息便可

下方就是對signalState和otherState的相關信息進行的打印 ,從打印信息中咱們能夠看出,儘管在observerWithState()函數中是以參數的形式獲取的signalState和otherState,可是其內存地址是不變的,獨一份。並且當這兩個都有lastestValue的狀況下,合併信號量的觀察者纔會收到相應的Value事件。具體以下所示。

  

 

 

 3、Latest合併原理圖

針對上述的代碼實現,以及參考以前博客中原理圖的形式,因而乎咱們給出了下方的這個原理圖。原理圖應該是清晰明瞭,一目瞭然的,在此就不作過多的贅述了。經過下圖的結構,咱們不難看出,combineLatestSignal信號量仍然是能夠進行鏈式發展的。

 

 

在Signal.swift文件中關於SignalProtocol的擴展的方法中,基本上是按照上述的套路來擴展的。大致就是一個方法返回一個新的信號量,這個新的信號量與原始信號量間經過橋接信號量來進行關聯。不一樣的方法在處理原信號量往新的信號量發送事件時,在中間所作的事情不一樣。Signal.swift文件中還有好多相似的方法,在此就不一一進行介紹了,若是你對某個方法的實現感興趣,能夠採用上述的套路來進行解析。

今天的博客就先到這兒,下篇博客咱們會繼續解析ReactiveSwift框架中的其餘內容。

上述代碼github分享地址:https://github.com/lizelu/TipSwiftForRac 

相關文章
相關標籤/搜索