上篇博客我們聊了observe()、map()、filter()延展函數(shù)的具體實(shí)現(xiàn)方式以及使用方式。我們?cè)谥暗牟┛椭幸呀?jīng)聊過(guò),Signal的主要功能是位于SignalProtocol的協(xié)議延展中的,而且延展函數(shù)是非常的多的。今天博客中我們繼續(xù)來(lái)聊SignalProtocol中那些比較核心的延展實(shí)現(xiàn)。本篇博客我們就來(lái)聊一下take()函數(shù)的使用以及實(shí)現(xiàn)方式,并且再聊一下Signal中collect()的相關(guān)實(shí)現(xiàn)。
一、take(first)
本部分我們就來(lái)聊一下take(first)的使用方式以及具體的實(shí)現(xiàn)方式。與上篇博客的套路類似,我們聊完代碼后,依然會(huì)給出take(first)函數(shù)的運(yùn)作方式。如果你看過(guò)上篇博客的內(nèi)容的話,那么take(first)方法是比較好理解的。因?yàn)?span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);">take(first)也是可以鏈?zhǔn)桨l(fā)展的,并且使用時(shí)的整體結(jié)構(gòu)與map()和filter()方法差不多,只不過(guò)后兩者接收的是一個(gè)閉包,而take(first)方法接收的是一個(gè)值罷了。
1、take(first)方法的使用
下方示例是ReactiveSwift官方給出的take(first)的使用示例,對(duì)其解釋如下:
首先還是通過(guò)pipe()函數(shù)來(lái)創(chuàng)建一個(gè)signal信號(hào)量,并獲的其內(nèi)置的observer。
然后通過(guò)調(diào)用signal的take(first)方法來(lái)創(chuàng)建一個(gè)新的信號(hào)量takeSignal。在調(diào)用take(first)時(shí),傳入的參數(shù)是3.
接著創(chuàng)建一個(gè)觀察者subscriber,并給出該觀察者在收到Value事件的處理閉包。
最后就是調(diào)用signal內(nèi)置的observer來(lái)發(fā)送Value事件了。
從下方代碼片段的輸出結(jié)果我們不難看出,發(fā)出的4個(gè)Value事件中只有前三個(gè)事件會(huì)被takeSignal的觀察者收到。而其他的takeSignal的觀察者是收不到的。從這一點(diǎn)我們就能明確的看出take(first)函數(shù)錯(cuò)創(chuàng)建的信號(hào)量的功能。take()的參數(shù)如果是N的話,那么就表示,take()所返回的信號(hào)量只能接受原信號(hào)量所發(fā)送事件的前N個(gè)。
2、take(first)方法的具體實(shí)現(xiàn)
看完take(first)方法的使用方式,接下來(lái)我們就來(lái)看一下take(first)的具體代碼實(shí)現(xiàn)。下方的SignalProtocol的延展就是take(first)方法的實(shí)現(xiàn),解釋如下:
take()方法也會(huì)返回一個(gè)新的Signal對(duì)象,也是可以鏈?zhǔn)桨l(fā)展的,不過(guò)在創(chuàng)建Signal對(duì)象時(shí)添加了一些條件判斷。
首先必須保證count為非負(fù)數(shù)的值。
然后當(dāng)count為0時(shí),直接執(zhí)行新信號(hào)量中observer的sendCompleted()方法,結(jié)束事件的接收。
當(dāng)count > 0時(shí),就創(chuàng)建一個(gè)take計(jì)數(shù)變量來(lái)記錄接收Value事件的次數(shù),如果take == count時(shí),說(shuō)明接收事件的次數(shù)已達(dá)到上限。就調(diào)用sendCompleted()方法,結(jié)束新返回信號(hào)量的觀察者接收消息。
3、執(zhí)行原理圖
take()函數(shù)的執(zhí)行過(guò)程與map()和filter()函數(shù)差不多,都是可以鏈?zhǔn)桨l(fā)展的。新創(chuàng)建的Signal對(duì)象與之前對(duì)象間都會(huì)有一個(gè)橋接觀察者。這幾個(gè)函數(shù)間的不同就在于這個(gè)橋接觀察者在發(fā)送消息所遵循的條件不同。下方就是該執(zhí)行原理圖:
二、Collection的使用
接下來(lái)我們來(lái)看一下接收集合類型的信號(hào)量。Signal的collect()相關(guān)的方法會(huì)生成一個(gè)新的信號(hào)量,而該信號(hào)量可以接受之前信號(hào)量的集合。也就是說(shuō)信號(hào)量的值是成批發(fā)送的。本部分我們就來(lái)聊聊信號(hào)量中的集合的使用方式以及具體的代碼實(shí)現(xiàn)方式。下方是collec相關(guān)的延展方法的使用示例。
接下來(lái)我們就來(lái)一一列舉一下集合信號(hào)量的使用方式,在ReactiveSwift中,主要有4中集合信號(hào)量的使用方式,下面將會(huì)一一列舉。
1、collect()
下方代碼片段就是collect()方法的使用示例,解釋如下:
首先調(diào)用signal對(duì)象的collect()方法生成一個(gè)新的信號(hào)量collectionSignal。
然后給這個(gè)集合信號(hào)量collectionSignal關(guān)聯(lián)一個(gè)觀察者subscriber。
然后調(diào)用原來(lái)signal的observer來(lái)連續(xù)的發(fā)送信號(hào)量,信號(hào)量的值分別為1、2、3、4。最后調(diào)用一下sendCompleted()方法表示信號(hào)量發(fā)送完畢。
最后我們可以看到,collectionSignal的觀察者會(huì)以集合的形式接收到了上述發(fā)送的信號(hào)量的值,如下所示。
2、collect(count)
collect(count)該方法比上述方法多了一個(gè)count參數(shù),該參數(shù)表示集合可容納元素的最大值,當(dāng)接收消息的個(gè)數(shù)為count時(shí),那么就將該集合進(jìn)行輸出,并開(kāi)始下一個(gè)集合的積累。下方就是collect(count)的使用方式。
從下方代碼片段的輸出結(jié)果中我們可以看到,輸出結(jié)果是兩個(gè)集合,因?yàn)榧显貍€(gè)數(shù)的最大值我們?cè)O(shè)置的為3。所以每個(gè)集合最多是3個(gè)值。
3、collect(_ predicate: @escaping (_ values: [Value]) -> Bool)
該方法接收的是一個(gè)條件閉包參數(shù),也就是說(shuō)predictcate是一個(gè)返回Bool類型的條件閉包,閉包中的內(nèi)容由調(diào)用者來(lái)提供。該方法可以根據(jù)該條件閉包的結(jié)果來(lái)判斷是否將已經(jīng)收到的信號(hào)量的值進(jìn)行打包發(fā)送。下方打包發(fā)送的條件是集合中的值的和恰好等于8時(shí)才會(huì)發(fā)送。
4、collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool)
該函數(shù)與上述還是類似,也是接收一個(gè)條件閉包,只不過(guò)給條件閉包的參數(shù)除了當(dāng)前集合內(nèi)的元素?cái)?shù)組外,還有一個(gè)當(dāng)前接收但尚未入集合的信號(hào)量的值。我們可以根據(jù)這兩個(gè)參數(shù)做一些判斷,然后在決定是否進(jìn)行結(jié)合信號(hào)量的發(fā)送。
下方代碼片段的意思是如果當(dāng)前發(fā)送的值為7,那么就將之前的集合進(jìn)行發(fā)送,發(fā)送后并清空,然后將當(dāng)前為7的值加入到清空后的集合中。下方是調(diào)用方式以及輸出結(jié)果。
三、Collection相關(guān)信號(hào)量的實(shí)現(xiàn)方式
上面我們看完了collect()及其相關(guān)方式的使用示例,接下來(lái)我我們就來(lái)看以前其內(nèi)部具體的代碼實(shí)現(xiàn)了。本部分就來(lái)看一下相關(guān)的代碼實(shí)現(xiàn)細(xì)節(jié)。
1、CollectState<Value>的實(shí)現(xiàn)
首先我們先來(lái)看一下CollectState的實(shí)現(xiàn)。CollectState就是二次封裝的數(shù)組集合,封裝后更適合我們集合信號(hào)量進(jìn)行元素的存儲(chǔ)和清空。也就是說(shuō),集合信號(hào)量所接收的信號(hào)量的值,是暫存在CollectState這個(gè)泛型集合中的。下方就是CollectState<Value>的實(shí)現(xiàn)方式。
該代碼比較簡(jiǎn)單就是對(duì)數(shù)組進(jìn)行的二次封裝,其中的append(value)方法就負(fù)責(zé)往數(shù)組中添加元素,而flush()方法則負(fù)責(zé)將數(shù)組進(jìn)行清空。isEmpty計(jì)算屬性則用來(lái)判斷values數(shù)組是否為空。
2、collect(_ predicate: @escaping (_ values: [Value]) -> Bool)方法的實(shí)現(xiàn)
接下來(lái)我們就來(lái)看一下collect(_ predicate: @escaping (_ values: [Value]) -> Bool)方法的實(shí)現(xiàn),該方法中的整體結(jié)構(gòu)與take()以及之前聊的map()、filter()函數(shù)相似,都是返回一個(gè)新的信號(hào)量,并且將這個(gè)新的信號(hào)量的Observer與之前信號(hào)量Bag中的一個(gè)Observer對(duì)象的事件進(jìn)行關(guān)聯(lián)。對(duì)下方代碼片段的解釋如下:
首先在創(chuàng)建新的信號(hào)量的構(gòu)造器尾隨閉包中創(chuàng)建了一個(gè)類型為CollectState<Value>的state,該state集合主要用來(lái)暫存原始信號(hào)量發(fā)送過(guò)來(lái)的值value。而這個(gè)新的信號(hào)量的類型為Signal<[Value], Error>類型,也就是說(shuō)這個(gè)新創(chuàng)建的信號(hào)量發(fā)送的值是一個(gè)集合類型。
然后在處理之前信號(hào)量發(fā)送事件時(shí),將取出來(lái)的值append()到state集合中,然后判斷predicate()閉包條件的值,如果predicate()條件成立,則集合信號(hào)量向其觀察者發(fā)送state集合,發(fā)送后并清除掉state中的元素的值。
當(dāng)接收到原信號(hào)量的sendCompleted()事件時(shí),集合信號(hào)量先將stata中的元素發(fā)送出去,然后調(diào)用其本身的sendCompleted()結(jié)束信號(hào)量的發(fā)送。
3、collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool)
該方法的實(shí)現(xiàn)與上述方法的實(shí)現(xiàn)極為相識(shí),只不過(guò)是閉包條件所攜帶的參數(shù)不同,并且處理?xiàng)l件的方式也不同。由下方代碼我們不難看出,當(dāng)條件閉包成立時(shí),集合信號(hào)量進(jìn)行事件發(fā)送,然后將state集合進(jìn)行情況,然后在將當(dāng)前的值添加到已經(jīng)被清空的state集合中。
也就是說(shuō),當(dāng)條件成立時(shí)所發(fā)送的集合中是不包括當(dāng)前所接收到的來(lái)著原始信號(hào)量的值的。具體如下所示:
4、collect()和collect(count)的實(shí)現(xiàn)
這兩個(gè)方式的實(shí)現(xiàn)就比較簡(jiǎn)單主要是調(diào)用上述方法,給上述方法的條件閉包傳入不同的值。因?qū)崿F(xiàn)方法比較簡(jiǎn)單,在此就不做過(guò)多贅述了。
四、collect()工作原理圖
上面聊完collect()的具體工作實(shí)現(xiàn),我們?cè)賮?lái)看一下collect()的工作原理圖,因?yàn)槠浯a實(shí)現(xiàn)與map()、filter()、take()等方法類似,所以原理圖也差不多。下方就是collect()的工作原理圖。
從下方的工作原理圖我們清楚的可以看到,原信號(hào)量Signal發(fā)送的是value, collectSignal收到這個(gè)value值后,將其暫存到[value]集合中,當(dāng)predicate()閉包的條件成立時(shí),會(huì)調(diào)用collectSignal的obser的send(value)方法,將集合[value]發(fā)送給collectSignal的觀察者。如下所示:
今天的博客就先到這兒,下篇博客我們會(huì)繼續(xù)解析ReactiveSwift框架中的其他內(nèi)容。
上述代碼github分享地址:https://github.com/lizelu/TipSwiftForRac
作者:青玉伏案
出處:http://www.cnblogs.com/ludashi/
本文版權(quán)歸作者和共博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
如果文中有什么錯(cuò)誤,歡迎指出。以免更多的人被誤導(dǎo)。
http://www.cnblogs.com/ludashi/p/6971897.html