(这篇文章原来发布在 csdn ,现在 blog 迁移过来,并用 Markdown 重新排版以及修改)
racsignal 的信号有冷热之分,简单来说所谓冷信号可以理解为被动的,只有当有订阅者的情况下,才会发布消息,且每订阅一次,重复发一次消息。而热信号则不依赖与订阅者,当它需要发消息的时候,不论有没有订阅者,都会发送。
冷信号如下:
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"send");
[subscriber sendNext:@"sender"];
[subscriber sendCompleted];
return nil;
}]; NSLog(@"start");
[[RACScheduler mainThreadScheduler] afterDelay:0.5 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 recveive: %@", x);
}];
}];
[[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 recveive: %@", x);
}];
}];
其输出如下
2016-02-18 21:00:11.190 ReactiveExample[46349:4307881] start
2016-02-18 21:00:11.733 ReactiveExample[46349:4307881] send
2016-02-18 21:00:11.733 ReactiveExample[46349:4307881] Subscriber 1 recveive: sender
2016-02-18 21:00:12.291 ReactiveExample[46349:4307881] send
2016-02-18 21:00:12.291 ReactiveExample[46349:4307881] Subscriber 2 recveive: sender
可见,只有有订阅者的情况下,才发送消息,并且每来一个订阅者,重新发生一次,冷信号是没有状态的。
而热信号是有状态的,可以将上述冷信号转化为热信号,代码如下
RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"send");
[subscriber sendNext:@"sender"];
[subscriber sendCompleted];
return nil;
}] multicast:[RACSubject subject]] autoconnect];
NSLog(@"start");
[[RACScheduler mainThreadScheduler] afterDelay:0.5 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 recveive: %@", x);
}];
}];
[[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 recveive: %@", x);
}];
}];
,这里的signal是热信号,它会在第一次被订阅的时候被激活,其输出如下
2016-02-19 19:59:13.611 ReactiveExample[70352:6183597] start
2016-02-19 19:59:14.140 ReactiveExample[70352:6183597] send
2016-02-19 19:59:14.141 ReactiveExample[70352:6183597] Subscriber 1 recveive: sender
可见,第二次订阅并没有再次触发 signal 信号,且由于 signal 是在启动后 0.5s 发出的信号,因此启动后 1s 订阅者错过了 signal 发出的消息。
当然,热信号其实也有多种类型,上面冷信号转热信号是通过 RACSubject 转化,下面也可以通过 RACReplaySubject 来转换
RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"send");
[subscriber sendNext:@"sender"];
[subscriber sendCompleted];
return nil;
}] multicast:[RACReplaySubject subject]] autoconnect];
NSLog(@"start");
[[RACScheduler mainThreadScheduler] afterDelay:0.5 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 recveive: %@", x);
}];
}];
[[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 recveive: %@", x);
}];
}];
输出如下,
2016-02-19 20:13:56.996 ReactiveExample[70544:6255982] start
2016-02-19 20:13:57.545 ReactiveExample[70544:6255982] send
2016-02-19 20:13:57.545 ReactiveExample[70544:6255982] Subscriber 1 recveive: sender
2016-02-19 20:13:58.070 ReactiveExample[70544:6255982] Subscriber 2 recveive: sender
对比通过 RACSubject 转化的输出结果可以发现,这里 0.5s ,以及 1s 订阅的两个订阅者都收到了 signal 发出的信号。RACReplaySubject 具有缓冲功能,能够收到历史信息。
说到这里,同学们可能会疑惑了,那 RACReplaySubject 跟冷信号有什么区别呢?细心的同学会发现,在冷信号代码示例中,NSLog(@"send") ;输出了两次,而在 RACReplaySubject 实例代码中 NSLog(@"send");只输出了一次。这就是区别了,冷信号会重复触发 signal 里面的逻辑,而 RACReplaySubject 只是重复发出信号而已。当然冷信号转热信号的方式还有多种,有兴趣的同学可以研究一下其官网文档