上篇博客咱們對Signal的基本實現以及Signal的面向協議擴展進行了介紹, 詳細內容請移步於《Signal中的靜態屬性靜態方法以及面向協議擴展》。而且聊了Signal的全部的g功能擴展都是放在Signal所實現的SignalProtocol協議的擴展中的。本篇博客就沿襲上篇博客的內容,咱們來聊一下SignalProtocol的部分擴展。本篇博客咱們主要來聊一下對Signal添加Observer的observe()方法擴展的具體實現,而且聊一下Signal的Map和Filter相關的功能擴展的具體實現。html
固然咱們在聊相關源碼的具體實現時,會給出相關的測試用例,而後再根據測試用例來理解其代碼實現。git
1、observe()方法的擴展github
首先咱們來看一下observe()方法的擴展。經過前幾篇博客的介紹,咱們知道Siganl與Observer之間的關聯是經過observe()方法來實現的。而observe()方法的核心實如今上篇博客中已經進行了詳細介紹。而在協議擴展中又對observe()方法進行了一些擴展,這些擴展主要是針對一些特定功能爲observe()的使用方式添加快捷調用方式。閉包
一、observe()方法擴展的具體實現app
下方個SignalProtocol的延展主要是對observe()方法的擴展,在每一個擴展方法中最後仍是得調用Signal類中所實現的observe()方法。仍是那句話,下方的這些observe()方法的擴展主要仍是Signal類中observe()方法的快捷方式。下方將對observe()的每一個快捷方法進行介紹。框架
observe(action) : 該方法傳入的是一個Action閉包,該Action閉包其實就是Observer類中的Action閉包。也就是在調用observe(action)方法時,爲Observer的 Action提供了閉包體。而在observe(action)方法中要作的就是實例化Observer對象,並將該對象傳給Signal的observe()方法。稍後會給出該擴展方法的使用過程。
observeResult(result):該擴展方法是將Observer的value事件和failed事件分別轉換成Result枚舉的success和failure。
observeCompleted(completed): 該擴展方法所接收的閉包就是Observer接收completed事件所執行的閉包。
observeFailed(failed): 該擴展方法所接收的閉包就是Observer接收failed事件所執行的閉包。
observeInterrupted(interrupted): 該擴展方法所接收的閉包就是Observer接收interrupted事件所執行的閉包。
從下方代碼片斷中咱們不難看出,都是在Signal的observe()方法的基礎上作的擴展,本質上就是observe()方法的特定使用的快捷方式。函數
二、上述擴展的使用方式post
看完實現,在看上述方法的使用方式就簡單多了。下方代碼片斷就是上述擴展中每一個方法的使用方式。咱們能夠根據具體的業務場景以及具體的功能來選擇實現那種方法來知足本身的開發需求。從下方每一個方法中的調用方式能夠看出,每一個方法在調用時所提供的尾隨閉包就是該方法所表示的快捷方式。測試
固然,下方全部的方法,咱們均可以使用Signal中的observe()方法來實現,只不過沒有下方這些方法方便快捷。url
2、SignalProtocol的Map擴展
在《ReactiveSwift源碼解析之Event與Observer》這篇博客中咱們聊了Event的Map函數,主要是將一個類型的Event(如Event<Value, Error>)轉換成另外一個Event類型(如Event<U, Error>)。Signal的Map函數也不例外,也是將一個類型的Signal轉換成另外一個類型的Signal。固然,Signal的Map函數本質上仍是使用了Event的Map函數。
根據以前對ReactiveSwift框架的解析,咱們不難發現Signal、Observer以及Event三者要想進行溝通是其泛型類型必須是相同的,也就是一套的。Map函數就是爲了解決Signal類型與Observer的類型不匹配而生的。也就是說咱們能夠經過Map函數的處理,一個Int類型的Signal能夠發送給String類型的Observer的,若是沒有Map函數的支持,是作不到這一點的。
能夠說Map函數是「適配器模式」的一種應用方式。能夠將不一樣類型的信號量和觀察者進行適配使其正常通訊。接下來咱們就來看一下SignalProtocol協議的Map相關的擴展以及使用方式。
一、map<U>() -> Signal<U, Error> 映射函數
map<U>()就是擴展中的Map相關函數之一。該函數是一個泛型函數,其返還值是一個Signal<U, Error>類型的對象。也就是說,一個Signal<Value, Error>類型的信號量能夠經過map<U>()函數映射成一個Signal<U, Error>類型的信號量。固然map<U>()函數的參數是一個尾隨閉包,該閉包有map函數的調用者提供,目的就是爲了讓用戶自定義兩個信號量之間的映射規則。
首先咱們來看一下map函數的使用方式,下方代碼片斷中是map函數的使用示例以及輸出結果,下方是對這段代碼的解釋:
首先咱們經過Signal的 pipe()靜態方法建立了一個類型爲 Signal<Int, NoError>的信號量signal。
而後經過signal的map函數建立了一個新的類型爲 Signal<String, NoError>的信號量 mappedSignal。map函數的尾隨閉包中就是映射規則,其中value是Int類型,而返回值是String類型。
而後建立了一個 Observer<String, NoError>類型的觀察者 subscriber, 並將 subscriber與 mappedSignal進行關聯
最後咱們調用 signal的 observer對象發送value事件,該事件所攜帶的值爲整數10。由輸出結果咱們能夠知道,與 mappedSignal關聯的觀察者 subscriber儘管只接收String類型的事件,可是通過map函數的處理此刻也是能夠收到來自signal的整數值信號量的。
看完map函數的用法後咱們來看一下其具體的代碼實現。下方就是上述示例所調用的map()函數的具體實現代碼。在map()函數中返回了一個類型爲Signal<U, Error>的信號量對象。在Signal的構造器的尾隨閉包中又調用了observe(action)方法將新建立的Signal的observer對象所對應的action添加到了以前Signal對象中。
上述代碼的執行過程也許有些繞,咱們能夠經過一張簡圖來看一下上述代碼的執行過程。下方是對該過程進一步的解釋:
首先類型爲 Signal<Value, Error>的signal對象調用其 map<U>()函數生成了一個新的類型爲 Signal<U, Error>的newSignal對象。
而後經過Event的 map<U>()函數,將signal對象中類型爲 Event<Value, Error>的事件經過調用事件的map<U>()函數將其映射成類型爲 Event<U, Error>的newEvent事件對象。
而後咱們將新的 newEvent添加到 newSignal的 observer的 action中。
而後使用 newSignal的 observer的action建立一個類型爲 Observer<Value, Error>的newObserver對象。
最後將這個新的 newObserver對象添加到舊的 signal的 Bag中。
上述是代碼的調用步驟,咱們能夠看一下具體的執行過程,以下圖所示。從下圖的結構咱們不難看出map()函數是鏈式發展的,下發的mappedSignal還能夠調用其本身的map()函數來生成新的Signal對象。在這個鏈上的全部Observer都會接受到最原始的Signal對象所發出的事件消息。signal與mappedSignal橋接的最終手段仍是Event的map()函數。
二、mapError<F>() -> Signal<U, F> 映射函數
mapError<F>()映射函數的實現機制和使用方式與上述的映射函數即爲類似。只不過該映射函數使用了Event的mapError<F>()函數。因該映射仍是的實現方式與上述函數相似,在此就不作過多贅述了。
關於lazyMap<U>()的實現和使用方式,咱們暫且不說,後邊聊到SignalProducer以及Flatten時咱們再作補充。
3、SignalProtocol的filter擴展
Filter顧明思議,就是用來過濾東西的。若是你理解上述map的工做原理的話,Filter就顯得簡單多了。Filter的工做原理以及實現方式與map類似,只不過將Event的map改爲了過濾條件。首先咱們將會給出Filter的使用方式,而後在該處Filter的代碼實現方式並給出工做原理圖。
一、Filter的使用方式
關於Filter的使用,咱們就使用ReactiveSwift官方的示例,下方是對該示例的解釋:
首先使用pipe建立一個signal,而後獲取到該signal發送消息的句柄observer。
而後經過調用signal的filter()函數來獲取過濾信號量filteredSignal,filter()函數的尾隨閉包中跟着的是過濾條件。
而後往filteredSignal信號量中添加觀察者subscriber。
當使用signal信號量發送事件時,符合過濾條件的事件纔會被過濾信號量filteredSignal所關聯的觀察者接收
下方截圖中咱們的過濾條件是事件綁定的值必須大於12,也就大於12的Value事件纔會被觀察者接受,因此輸出的結果只有13和14兩個,具體以下所示。
二、Filter的代碼實現
看完Filter的使用方式,接下來咱們來看一下Filter的代碼實現方式。下方代碼片斷就是filter函數的具體實現,從代碼結構上來看,與上述的map函數差很少,都是返回一個新的Signal對象,新的Signal對象與原來的Signal對象之間有一個橋接觀察者來進行通訊的。self.observer()函數後邊的閉包就是橋接觀察者從原信號量中發出的事件,而後在該事件中根據過濾條件來判斷是否向新的信號量所綁定的全部觀察者轉發該事件。
從下方代碼中咱們明確的能夠看出,當條件閉包predicate()的值爲true時,observer就會對值的事件進行轉發,而後過濾信號量所綁定的觀察者就能夠收到這些事件了。
三、執行原理圖
下方就是filter的執行原理圖,該圖的結構與map()函數的執行結構相似。從下方圖中咱們不難看出,filter()函數也是支持鏈式發展的,就是能夠在新的filterSignal的對象上咱們任然能夠添加新的過濾條件條件。由於不管是map()仍是filter()函數都會返回一個新的Signal對象,而且二者都是能夠鏈式發展的,因此咱們能夠這樣去寫signal.map().filter().map().filter().filter()……。
在filter下方還有一個filterMap<U>()函數,該函數的主要功能是用來Map的,代碼實現方式與與上述的filter相似,只不過是map的功能,可是該map功能有過濾功能,能夠過濾掉nil的值。擴展中的skipNil()方法中調用的就是filterMap<U>()函數,在此就不作過多贅述了。
今天的博客就先到這兒,下篇博客咱們會繼續解析ReactiveSwift框架中的其餘內容。
上述代碼github分享地址:https://github.com/lizelu/TipSwiftForRac