RAC常用方法replay、replayLast、replayLazily区别详解-进阶篇

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也能收到
}];

对比一下控制台打印结果如下图:


1.png

把上面代码进行简单修改一下

__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变量是最后一次订阅后的值,所以此次发送的消息,只有最后一个订阅者能接收到

代码执行结果如下:

44.png

二、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
}];

对比一下控制台打印结果如下图:

---.png

三、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

控制台打印结果如下图:


0.png

四、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

控制台打印结果如下图:

4.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容