这里的数据源
和sendXXX
,可以理解为函数的参数
和返回值
。当Signal处理完数据后,可以向下一个Signal
或Subscriber
传送数据。可以看到上半部分的两个Signal
是冷的(cold)
,相当于实现了某个函数,但该函数没有被调用。同时也说明了Signal
可以被组合使用,比如RACSignal *signalB = [signalA map:^id(id x){return x}]
,或RACSignal *signalB = [signalA take:1]
等等。
当signal
被subscribe
时,就会处于热(hot)
的状态,也就是该函数会被执行。比如上面的第二张图,首先signalA
可能发了一个网络请求,拿到结果后,把数据通过sendNex
t方法传递到下一个signal
,signalB
可以根据需要做进一步处理,比如转换成相应的Model
,转换完后再sendNext
到subscriber
,subscriber
拿到数据后,再改变ViewModel
,同时因为View已经绑定了ViewModel
,所以拿到的数据会自动在View里呈现。
还有,一个signal
可以被多个subscriber
订阅,这里怕显得太乱就没有画出来,但每次被新的subscriber
订阅时,都会导致数据源的处理逻辑被触发一次,这很有可能导致意想不到的结果,需要注意一下。
什么是combineLatestWith?
combineLatestWith
和数学中的逻辑与(&&)
的概念是一样的。只有两个两个信号同时发送了sendNext
事件,才会触发;
有趣的是,merge
和数学中的逻辑或(||)
的概念是一样的,只要其中一个信号发送了sendNext事件,就会触发;
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@signalA1];
[subscriber sendNext:@signalA2];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@signalB1];
[subscriber sendNext:@signalB2];
return nil;
}];
// 把两个信号组合成一个信号
RACSignal *combineSignal = [signalA combineLatestWith:signalB];
[combineSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
结果打印:
signalA2 signalB1
signalA2 signalB2
Reactive Cocoa的使用
combineLatest(聚合信号):把不同信号产生的最新的值聚合在一起,并生成一个新的信号。每次这两个源信号的任何一个产生新值时,reduce block都会执行,block的返回值会发给下一个信号。
Map(转换):Map是接收到信号后,对信号的返回值处理,然后根据需要改变信号的返回值,继续传递该信号。
Injecting effects(注入效果):对信号做一些处理 -doNext: -doError: -doCompleted:。
Filtering(过滤):过滤不符合需求的信号。
FlattenMap(平铺拓扑):收到信号后,对信号返回值进行处理后,返回一个新的信号,可以改变信号的返回值。
Flatten(平铺):当订阅者的数量达到最大当前订阅数的时候,合并接收者发送的各种信号到一个平铺信号中。新的信号会像其他信号一样被排队、订阅。
Concat(拼接):一个信号拼接到另一个信号后面
FlattenMap和Map的区别:
Map
是通过FlattenMap
来实现的,Map只是改变分发的值。而FlattenMap不仅可以获得上一个信号的值,还能激活下一个信号,形成这种链式反应。Map是FlattenMap在流中信号数量为1,而且信号值是block的返回值的特殊情况。Map是改变一个信号的返回值,FlattenMap是创建一个新的信号。
RACSignal (Debugging)
/// Logs all events that the receiver sends.
- (RACSignal *)logAll;
/// Logs each `next` that the receiver sends.
- (RACSignal *)logNext;
/// Logs any error that the receiver sends.
- (RACSignal *)logError;
/// Logs any `completed` event that the receiver sends.
- (RACSignal *)logCompleted;