上篇博客咱们聊了observe()、map()、filter()延展函数的具体实现方式以及使用方式。咱们在以前的博客中已经聊过,Signal的主要功能是位于SignalProtocol的协议延展中的,并且延展函数是很是的多的。今天博客中咱们继续来聊SignalProtocol中那些比较核心的延展实现。本篇博客咱们就来聊一下take()函数的使用以及实现方式,而且再聊一下Signal中collect()的相关实现。git
1、take(first)github
本部分咱们就来聊一下take(first)的使用方式以及具体的实现方式。与上篇博客的套路相似,咱们聊完代码后,依然会给出take(first)函数的运做方式。若是你看过上篇博客的内容的话,那么take(first)方法是比较好理解的。由于take(first)也是能够链式发展的,而且使用时的总体结构与map()和filter()方法差很少,只不事后二者接收的是一个闭包,而take(first)方法接收的是一个值罢了。api
一、take(first)方法的使用数组
下方示例是ReactiveSwift官方给出的take(first)的使用示例,对其解释以下:闭包
首先仍是经过 pipe()函数来建立一个 signal信号量,并获的其内置的 observer。
而后经过调用signal的 take(first)方法来建立一个新的信号量 takeSignal。在调用 take(first)时,传入的参数是3.
接着建立一个观察者 subscriber,并给出该观察者在收到Value事件的处理闭包。
最后就是调用 signal内置的 observer来发送 Value事件了。
从下方代码片断的输出结果咱们不难看出,发出的4个Value事件中只有前三个事件会被takeSignal的观察者收到。而其余的takeSignal的观察者是收不到的。从这一点咱们就能明确的看出take(first)函数错建立的信号量的功能。take()的参数若是是N的话,那么就表示,take()所返回的信号量只能接受原信号量所发送事件的前N个。app
二、take(first)方法的具体实现框架
看完take(first)方法的使用方式,接下来咱们就来看一下take(first)的具体代码实现。下方的SignalProtocol的延展就是take(first)方法的实现,解释以下:函数
take()方法也会返回一个新的Signal对象,也是能够链式发展的,不过在建立Signal对象时添加了一些条件判断。
首先必须保证 count为非负数的值。
而后当count为0时,直接执行新信号量中 observer的 sendCompleted()方法,结束事件的接收。
当 count > 0时,就建立一个take计数变量来记录接收Value事件的次数,若是 take == count时,说明接收事件的次数已达到上限。就调用 sendCompleted()方法,结束新返回信号量的观察者接收消息。
三、执行原理图spa
take()函数的执行过程与map()和filter()函数差很少,都是能够链式发展的。新建立的Signal对象与以前对象间都会有一个桥接观察者。这几个函数间的不一样就在于这个桥接观察者在发送消息所遵循的条件不一样。下方就是该执行原理图:server
2、Collection的使用
接下来咱们来看一下接收集合类型的信号量。Signal的collect()相关的方法会生成一个新的信号量,而该信号量能够接受以前信号量的集合。也就是说信号量的值是成批发送的。本部分咱们就来聊聊信号量中的集合的使用方式以及具体的代码实现方式。下方是collec相关的延展方法的使用示例。
接下来咱们就来一一列举一下集合信号量的使用方式,在ReactiveSwift中,主要有4中集合信号量的使用方式,下面将会一一列举。
一、collect()
下方代码片断就是collect()方法的使用示例,解释以下:
首先调用signal对象的 collect()方法生成一个新的信号量 collectionSignal。
而后给这个集合信号量 collectionSignal关联一个观察者 subscriber。
而后调用原来signal的 observer来连续的发送信号量,信号量的值分别为一、二、三、4。最后调用一下 sendCompleted()方法表示信号量发送完毕。
最后咱们能够看到, collectionSignal的观察者会以集合的形式接收到了上述发送的信号量的值,以下所示。
二、collect(count)
collect(count)该方法比上述方法多了一个count参数,该参数表示集合可容纳元素的最大值,当接收消息的个数为count时,那么就将该集合进行输出,并开始下一个集合的积累。下方就是collect(count)的使用方式。
从下方代码片断的输出结果中咱们能够看到,输出结果是两个集合,由于集合元素个数的最大值咱们设置的为3。因此每一个集合最可能是3个值。
三、collect(_ predicate: @escaping (_ values: [Value]) -> Bool)
该方法接收的是一个条件闭包参数,也就是说predictcate是一个返回Bool类型的条件闭包,闭包中的内容由调用者来提供。该方法能够根据该条件闭包的结果来判断是否将已经收到的信号量的值进行打包发送。下方打包发送的条件是集合中的值的和刚好等于8时才会发送。
四、collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool)
该函数与上述仍是相似,也是接收一个条件闭包,只不过给条件闭包的参数除了当前集合内的元素数组外,还有一个当前接收但还没有入集合的信号量的值。咱们能够根据这两个参数作一些判断,而后在决定是否进行结合信号量的发送。
下方代码片断的意思是若是当前发送的值为7,那么就将以前的集合进行发送,发送后并清空,而后将当前为7的值加入到清空后的集合中。下方是调用方式以及输出结果。
3、Collection相关信号量的实现方式
上面咱们看完了collect()及其相关方式的使用示例,接下来我咱们就来看之前其内部具体的代码实现了。本部分就来看一下相关的代码实现细节。
一、CollectState<Value>的实现
首先咱们先来看一下CollectState的实现。CollectState就是二次封装的数组集合,封装后更适合咱们集合信号量进行元素的存储和清空。也就是说,集合信号量所接收的信号量的值,是暂存在CollectState这个泛型集合中的。下方就是CollectState<Value>的实现方式。
该代码比较简单就是对数组进行的二次封装,其中的append(value)方法就负责往数组中添加元素,而flush()方法则负责将数组进行清空。isEmpty计算属性则用来判断values数组是否为空。
二、collect(_ predicate: @escaping (_ values: [Value]) -> Bool)方法的实现
接下来咱们就来看一下collect(_ predicate: @escaping (_ values: [Value]) -> Bool)方法的实现,该方法中的总体结构与take()以及以前聊的map()、filter()函数类似,都是返回一个新的信号量,而且将这个新的信号量的Observer与以前信号量Bag中的一个Observer对象的事件进行关联。对下方代码片断的解释以下:
首先在建立新的信号量的构造器尾随闭包中建立了一个类型为 CollectState<Value>的state,该state集合主要用来暂存原始信号量发送过来的值value。而这个新的信号量的类型为 Signal<[Value], Error>类型,也就是说这个新建立的信号量发送的值是一个集合类型。
而后在处理以前信号量发送事件时,将取出来的值 append()到state集合中,而后判断 predicate()闭包条件的值,若是 predicate()条件成立,则集合信号量向其观察者发送state集合,发送后并清除掉 state中的元素的值。
当接收到原信号量的 sendCompleted()事件时,集合信号量先将stata中的元素发送出去,而后调用其自己的 sendCompleted()结束信号量的发送。
三、collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool)
该方法的实现与上述方法的实现极为相识,只不过是闭包条件所携带的参数不一样,而且处理条件的方式也不一样。由下方代码咱们不难看出,当条件闭包成立时,集合信号量进行事件发送,而后将state集合进行状况,而后在将当前的值添加到已经被清空的state集合中。
也就是说,当条件成立时所发送的集合中是不包括当前所接收到的来着原始信号量的值的。具体以下所示:
四、collect()和collect(count)的实现
这两个方式的实现就比较简单主要是调用上述方法,给上述方法的条件闭包传入不一样的值。因实现方法比较简单,在此就不作过多赘述了。
4、collect()工做原理图
上面聊完collect()的具体工做实现,咱们再来看一下collect()的工做原理图,由于其代码实现与map()、filter()、take()等方法相似,因此原理图也差很少。下方就是collect()的工做原理图。
从下方的工做原理图咱们清楚的能够看到,原信号量Signal发送的是value, collectSignal收到这个value值后,将其暂存到[value]集合中,当predicate()闭包的条件成立时,会调用collectSignal的obser的send(value)方法,将集合[value]发送给collectSignal的观察者。以下所示:
今天的博客就先到这儿,下篇博客咱们会继续解析ReactiveSwift框架中的其余内容。
上述代码github分享地址:https://github.com/lizelu/TipSwiftForRac