ReactCocoa 版本号:V2.5
Language: ObjectC
XCode 版本号: V9.4
Note: 阅读本文章假设您已经有了一定的ReactCocoa基础知识
一、RACSingal (信号)
1.每次订阅信号,都会导致信号的订阅代码被调用,且参数subscriber的值每次都不一样。
2.订阅者只能收到订阅后发送的所有消息,无法收到之前发送的历史消息。
RACSignal *sig = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"我被订阅了,%@", subscriber); //每次有人订阅都会执行这段Block, subscriber每次值不一样
[subscriber sendNext:@"aaa"]; //发送消息:aaa
return nil;
}];
NSLog(@"11马上订阅信号"); //第一步打印
[sig subscribeNext:^(id x) { //一旦被订阅上面的订阅代码被执行
NSLog(@"11接收到:%@",x); //上面的订阅代码里发送了消息aaa,这里能收到
}];
NSLog(@"22马上订阅信号");
[sig subscribeNext:^(id x) { //又被订阅一次,导致上面的订阅代码再次执行
NSLog(@"222接收到:%@",x); //上面订阅代码里发送了消息aaa,这里能收到,上面的订阅者11也能收到
}];
对比一下控制台打印结果如下图:
把上面代码进行简单修改一下
__block id<RACSubscriber> s = nil;
RACSignal *sig = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"我被订阅了,%@", subscriber); //每次有人订阅都会执行这段Block, subscriber每次值不一样
s = subscriber; //保存到外部变量,让Block外面去发送消息
return nil;
}];
NSLog(@"马上发消息aaa");
[s sendNext:@"aaa"]; //sig信号此时还没有被订阅,上面的订阅代码没有执行,s此时值为nil,发送失败
NSLog(@"11马上订阅信号");
[sig subscribeNext:^(id x) { //一旦被订阅上面的订阅代码被执行,s变量不为空
NSLog(@"11接收到:%@",x); //由于上面的订阅代码里并没有发送消息,所以这里收不到任何消息
}];
NSLog(@"马上发消息bbb");
[s sendNext:@"bbb"]; //sig信号上面已经被订阅了,且s保存了上一次值,发送成功,上面订阅者11能收到消息
NSLog(@"22马上订阅信号");
[sig subscribeNext:^(id x) { //又被订阅一次,导致上面的订阅代码再次执行,s变量变成新的值
NSLog(@"222接收到:%@",x); //由于s变量更新后并没有发送消息,所以这里也接收不到消息
}];
NSLog(@"马上发消息ccc");
[s sendNext:@"ccc"]; //注意,s变量是最后一次订阅后的值,所以此次发送的消息,只有最后一个订阅者能接收到
代码执行结果如下:
二、replay :
1.调用replay,会导致源信号的订阅代码先被调用
2.信号多次被订阅不会重复执行源信号的订阅代码
3.订阅者能收到所有历史已经发送的、未来发送的所有消息。
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"开始发送"); //1.第一步执行。replay内部会先订阅此信号导致此Block会被调用
s = subscriber; //将发送者保存到外部变量,因为block外部需要发送信号
[s sendNext:@"aaa"]; //注意,此时此刻信号还没有订阅者
return nil;
}] replay];
NSLog(@"马上发送消息bbb");//2.第二步打印
[s sendNext:@"bbb"]; //此时此刻,信号还是没有订阅者
[sig subscribeNext:^(id x) {//订阅不会导致信号的订阅代码被调用
NSLog(@"11接收到:%@",x); //3.第三步执行,神奇的事情发生了,这里依然能接收到前面已经发送出去的消息aaa、bbb
}];
[s sendNext:@"ccc"]; //继续发送,会导致前面的订阅者收到消息:ccc
[s sendNext:@"ddd"]; //继续发送,会导致前面的订阅者收到消息:ddd
[s sendNext:@"eeee"];//继续发送,会导致前面的订阅者收到消息:eeee
[sig subscribeNext:^(id x) {
NSLog(@"222接收到:%@",x); //前面已经发送出去的消息都能收到:aaa、bbb、ccc、ddd、eeee
}];
对比一下控制台打印结果如下图:
三、replayLast :
1.调用replayLast,会导致源信号的订阅代码先被调用(与replay相同)
2.信号多次被订阅不会重复执行源信号的订阅代码(与replay相同)
3.订阅者只能收到历史已经发送的最近一条信息、未来发送的所有消息。(与replay唯一不同)
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"开始发送"); //1.第一步执行。replayLast内部会先订阅此信号导致此Block会被调用
s = subscriber; //将发送者保存到外部变量,因为block外部需要发送信号
[s sendNext:@"aaa"]; //注意,此时此刻信号还没有订阅者
return nil;
}] replayLast];
[s sendNext:@"bbb"]; //此时此刻,信号还是没有订阅者
[sig subscribeNext:^(id x) {
NSLog(@"11接收到:%@",x); //2.第二部执行,这里只能收到前面历史消息中最近的一条:bbb,无法收到aaa消息。
}];
[s sendNext:@"ccc"]; //继续发送,会导致前面的订阅者收到消息:ccc
[s sendNext:@"ddd"]; //继续发送,会导致前面的订阅者收到消息:ddd
[s sendNext:@"eeee"];//继续发送,会导致前面的订阅者收到消息:eeee
[sig subscribeNext:^(id x) {//再次订阅不会导致订阅代码再次执行
NSLog(@"222接收到:%@",x); //只能收到前面的最近一条消息:eeee
}];
[s sendNext:@"ffff"];//继续发送,会导致前面的两个订阅者都收到消息:ffff
控制台打印结果如下图:
四、replayLazily :
1.调用replayLazily,会导致源信号的订阅代码只在信号首次被订阅时调用(与replay唯一不同)
2.信号多次被订阅不会重复执行源信号的订阅代码(与replay相同)
3.订阅者能收到所有历史已经发送的、未来发送的所有消息。(与replay相同)
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"开始发送"); //首次订阅此信号导致此Block会被调用一次,此后不会调用
s = subscriber; //将发送者保存到外部变量,因为block外部需要发送信号
[s sendNext:@"aaa"];
return nil;
}] replayLazily];
NSLog(@"马上发送消息bbb");//1.第一步打印
[s sendNext:@"bbb"]; //此时此刻发送失败,因为上面Block未执行,s值是nil
NSLog(@"11马上订阅消息");//2.第二步打印
[sig subscribeNext:^(id x) {//首次订阅,上面的Block被执行
NSLog(@"11接收到:%@",x); //Block里发送了消息,此处收到消息:aaa
}];
[s sendNext:@"ccc"]; //继续发送,会导致前面的订阅者收到消息:ccc
[s sendNext:@"ddd"]; //继续发送,会导致前面的订阅者收到消息:ddd
[s sendNext:@"eeee"];//继续发送,会导致前面的订阅者收到消息:eeee
[sig subscribeNext:^(id x) {//再次订阅不会导致订阅代码再次执行
NSLog(@"222接收到:%@",x); //前面发送的消息全部能收到:aaa、ccc、ddd、eeee
}];
[s sendNext:@"ffff"];//继续发送,会导致前面的两个订阅者都收到消息:ffff
控制台打印结果如下图: