RACSignal
信号是ReactiveCocoa 中最基础概念之一就是。其中信号的实例为RACRACStream.它两个子类RACSignal 和 RACSequence.其中RACSequence用的较少。本次只分析RACSignal。
1 | RACSignal *signal = [RACSignal createSignal: |
试分析下。以上代码分别作了什么。首先这是一个RACSignal作用的过程。
当调用了RACSignal中createSignal函数的时候,会调用RACSignal的子类RACDynamicSignal的createSignal函数。
1 | + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe { |
而 RACDynamicSignal中 createSignal的函数做了什么呢?
1 | @implementation RACDynamicSignal |
可以通过源码看出。只是生成了一个实例。保存了传入的 didSubscribe。此时需要注意didSubscribe的类型。首先它是一个 block。他的参数是id<RACSubscriber>返回值是RACDisposable。那么现在我们已经保存了传入的didSubscribe。现在我们需要找到它执行的时机。
首先我们找到RACSignal (Subscription)这个RACSignal的分类。
1 | @implementation RACSignal (Subscription) |
可以看到在信号被订阅的时候统一都生成了一个RACSubscriber。并通过[self subscribe:o]传递下去。接下来我们来看RACDynamicSignal中subscribe这个函数的实现。
1 | @implementation RACDynamicSignal |
通过代码可以看到。调用了保存下来的didSubscribe这个block,同时将传入进来的subscriber当成参数传入进去。此时。我们便能确定。订阅式生成的subscriber和我们创建信号的传进来的subscriber。其实是同一个对象。那么接下来。我们来看下RACSubscriber到底作了什么。
1 | @interface RACSubscriber () |
此时再看示例代码。就简单明了了。整体的流程也就是分成以下几个部分。
1 | RACSignal *signal = [RACSignal createSignal: |
- 创建新号。同时保存
subscriber。等待信号被订阅是调用。 - 信号被订阅时,创建一个
RACSubscriber实例.将订阅是传入的nexterrorcompleted回调事件保存在创建的RACSubscriber实例中。 - 将创建的
RACSubscriber实例传入创建信号是保存的subscriberblock中 - 当
RACSubscriber被调用对应的函数的时候。内部调用对应保存的block。
基础使用原理分析
concat
1 | - (RACSignal *)concat:(RACSignal *)signal { |
调用concat时。首先创建了一个新的信号。订阅了第一个信号。当第一个信号结束的时候。开始订阅第二个信号。并将两个信号传递的消息通过新创建的信号的订阅者发送出去。
zipWith
1 | - (RACSignal *)zipWith:(RACSignal *)signal { |
原理和concat类似。创建新的信号。订阅传递进来的两个信号。匹配数据。通过新的信号的订阅者将组合好的数据发送出去。
bind
1 | - (RACSignal *)bind:(RACSignalBindBlock (^)(void))block { |
- 订阅当前的信号.
- 任何时候当前信号发送了一个数据,使用绑定的 block 转换它。
- 如果返回的是一个信号的话就订阅它。并在接收到数据时将其所有值传递给订阅者。
- 如果返回值要求停止则完成当前信号。
- 如果所有的信号都已经发送完毕。发送完成给当前订阅者。
- 如果信号发送的 error,将其转发给当前订阅者.
merge flaten
1 | + (RACSignal *)merge:(id<NSFastEnumeration>)signals { |
此处文字描述较为复杂。我会尽力说明。
- 调用 merge 的时候创建了一个新的信号,我们将其命名为 new_merge_signal.
- new_merge_signal 在被调用的时候。通过订阅者将需要 merge 的信号全部发送出去。
- new_merge_signal 主动调用了 flatten ,而 flatten 调用了 falttenMap。
- flattenMap 调用了 bind。
- bind 创建了一个新的信号,我们将其命名为 new_bind_signal。
- new_bind_signal 在被订阅的时候会主动订阅 new_merge_signal。new_merge_signal 在被订阅的时候会将所有需要 merge 的 signal 发送出去。 new_bind_signal 内部拿到需要 merge 的 signal 之后订阅所有需要合并的 signal。并将这些需要合并的 signal 发送的数据通过 new_bind_signal 的订阅者发送出去。