ReactCocoa 版本號:V2.5
Language: ObjectC
XCode 版本號: V9.4
Note: 閱讀本文章假設(shè)您已經(jīng)有了一定的ReactCocoa基礎(chǔ)知識(shí)
一、RACSingal (信號)
1.每次訂閱信號峡蟋,都會(huì)導(dǎo)致信號的訂閱代碼被調(diào)用坟桅,且參數(shù)subscriber的值每次都不一樣。
2.訂閱者只能收到訂閱后發(fā)送的所有消息蕊蝗,無法收到之前發(fā)送的歷史消息仅乓。
RACSignal *sig = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"我被訂閱了,%@", subscriber); //每次有人訂閱都會(huì)執(zhí)行這段Block, subscriber每次值不一樣
[subscriber sendNext:@"aaa"]; //發(fā)送消息:aaa
return nil;
}];
NSLog(@"11馬上訂閱信號"); //第一步打印
[sig subscribeNext:^(id x) { //一旦被訂閱上面的訂閱代碼被執(zhí)行
NSLog(@"11接收到:%@",x); //上面的訂閱代碼里發(fā)送了消息aaa,這里能收到
}];
NSLog(@"22馬上訂閱信號");
[sig subscribeNext:^(id x) { //又被訂閱一次蓬戚,導(dǎo)致上面的訂閱代碼再次執(zhí)行
NSLog(@"222接收到:%@",x); //上面訂閱代碼里發(fā)送了消息aaa方灾,這里能收到,上面的訂閱者11也能收到
}];
對比一下控制臺(tái)打印結(jié)果如下圖:
把上面代碼進(jìn)行簡單修改一下
__block id<RACSubscriber> s = nil;
RACSignal *sig = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"我被訂閱了,%@", subscriber); //每次有人訂閱都會(huì)執(zhí)行這段Block, subscriber每次值不一樣
s = subscriber; //保存到外部變量碌更,讓Block外面去發(fā)送消息
return nil;
}];
NSLog(@"馬上發(fā)消息aaa");
[s sendNext:@"aaa"]; //sig信號此時(shí)還沒有被訂閱裕偿,上面的訂閱代碼沒有執(zhí)行,s此時(shí)值為nil痛单,發(fā)送失敗
NSLog(@"11馬上訂閱信號");
[sig subscribeNext:^(id x) { //一旦被訂閱上面的訂閱代碼被執(zhí)行嘿棘,s變量不為空
NSLog(@"11接收到:%@",x); //由于上面的訂閱代碼里并沒有發(fā)送消息,所以這里收不到任何消息
}];
NSLog(@"馬上發(fā)消息bbb");
[s sendNext:@"bbb"]; //sig信號上面已經(jīng)被訂閱了旭绒,且s保存了上一次值鸟妙,發(fā)送成功,上面訂閱者11能收到消息
NSLog(@"22馬上訂閱信號");
[sig subscribeNext:^(id x) { //又被訂閱一次挥吵,導(dǎo)致上面的訂閱代碼再次執(zhí)行重父,s變量變成新的值
NSLog(@"222接收到:%@",x); //由于s變量更新后并沒有發(fā)送消息,所以這里也接收不到消息
}];
NSLog(@"馬上發(fā)消息ccc");
[s sendNext:@"ccc"]; //注意忽匈,s變量是最后一次訂閱后的值房午,所以此次發(fā)送的消息,只有最后一個(gè)訂閱者能接收到
代碼執(zhí)行結(jié)果如下:
二丹允、replay :
1.調(diào)用replay郭厌,會(huì)導(dǎo)致源信號的訂閱代碼先被調(diào)用
2.信號多次被訂閱不會(huì)重復(fù)執(zhí)行源信號的訂閱代碼
3.訂閱者能收到所有歷史已經(jīng)發(fā)送的、未來發(fā)送的所有消息雕蔽。
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"開始發(fā)送"); //1.第一步執(zhí)行折柠。replay內(nèi)部會(huì)先訂閱此信號導(dǎo)致此Block會(huì)被調(diào)用
s = subscriber; //將發(fā)送者保存到外部變量,因?yàn)閎lock外部需要發(fā)送信號
[s sendNext:@"aaa"]; //注意批狐,此時(shí)此刻信號還沒有訂閱者
return nil;
}] replay];
NSLog(@"馬上發(fā)送消息bbb");//2.第二步打印
[s sendNext:@"bbb"]; //此時(shí)此刻扇售,信號還是沒有訂閱者
[sig subscribeNext:^(id x) {//訂閱不會(huì)導(dǎo)致信號的訂閱代碼被調(diào)用
NSLog(@"11接收到:%@",x); //3.第三步執(zhí)行,神奇的事情發(fā)生了,這里依然能接收到前面已經(jīng)發(fā)送出去的消息aaa承冰、bbb
}];
[s sendNext:@"ccc"]; //繼續(xù)發(fā)送嘱根,會(huì)導(dǎo)致前面的訂閱者收到消息:ccc
[s sendNext:@"ddd"]; //繼續(xù)發(fā)送,會(huì)導(dǎo)致前面的訂閱者收到消息:ddd
[s sendNext:@"eeee"];//繼續(xù)發(fā)送巷懈,會(huì)導(dǎo)致前面的訂閱者收到消息:eeee
[sig subscribeNext:^(id x) {
NSLog(@"222接收到:%@",x); //前面已經(jīng)發(fā)送出去的消息都能收到:aaa该抒、bbb、ccc顶燕、ddd凑保、eeee
}];
對比一下控制臺(tái)打印結(jié)果如下圖:
三、replayLast :
1.調(diào)用replayLast涌攻,會(huì)導(dǎo)致源信號的訂閱代碼先被調(diào)用(與replay相同)
2.信號多次被訂閱不會(huì)重復(fù)執(zhí)行源信號的訂閱代碼(與replay相同)
3.訂閱者只能收到歷史已經(jīng)發(fā)送的最近一條信息欧引、未來發(fā)送的所有消息。(與replay唯一不同)
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"開始發(fā)送"); //1.第一步執(zhí)行恳谎。replayLast內(nèi)部會(huì)先訂閱此信號導(dǎo)致此Block會(huì)被調(diào)用
s = subscriber; //將發(fā)送者保存到外部變量芝此,因?yàn)閎lock外部需要發(fā)送信號
[s sendNext:@"aaa"]; //注意,此時(shí)此刻信號還沒有訂閱者
return nil;
}] replayLast];
[s sendNext:@"bbb"]; //此時(shí)此刻因痛,信號還是沒有訂閱者
[sig subscribeNext:^(id x) {
NSLog(@"11接收到:%@",x); //2.第二部執(zhí)行婚苹,這里只能收到前面歷史消息中最近的一條:bbb,無法收到aaa消息。
}];
[s sendNext:@"ccc"]; //繼續(xù)發(fā)送鸵膏,會(huì)導(dǎo)致前面的訂閱者收到消息:ccc
[s sendNext:@"ddd"]; //繼續(xù)發(fā)送膊升,會(huì)導(dǎo)致前面的訂閱者收到消息:ddd
[s sendNext:@"eeee"];//繼續(xù)發(fā)送,會(huì)導(dǎo)致前面的訂閱者收到消息:eeee
[sig subscribeNext:^(id x) {//再次訂閱不會(huì)導(dǎo)致訂閱代碼再次執(zhí)行
NSLog(@"222接收到:%@",x); //只能收到前面的最近一條消息:eeee
}];
[s sendNext:@"ffff"];//繼續(xù)發(fā)送谭企,會(huì)導(dǎo)致前面的兩個(gè)訂閱者都收到消息:ffff
控制臺(tái)打印結(jié)果如下圖:
四廓译、replayLazily :
1.調(diào)用replayLazily,會(huì)導(dǎo)致源信號的訂閱代碼只在信號首次被訂閱時(shí)調(diào)用(與replay唯一不同)
2.信號多次被訂閱不會(huì)重復(fù)執(zhí)行源信號的訂閱代碼(與replay相同)
3.訂閱者能收到所有歷史已經(jīng)發(fā)送的债查、未來發(fā)送的所有消息非区。(與replay相同)
__block id<RACSubscriber> s = nil;
RACSignal *sig = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"開始發(fā)送"); //首次訂閱此信號導(dǎo)致此Block會(huì)被調(diào)用一次,此后不會(huì)調(diào)用
s = subscriber; //將發(fā)送者保存到外部變量盹廷,因?yàn)閎lock外部需要發(fā)送信號
[s sendNext:@"aaa"];
return nil;
}] replayLazily];
NSLog(@"馬上發(fā)送消息bbb");//1.第一步打印
[s sendNext:@"bbb"]; //此時(shí)此刻發(fā)送失敗征绸,因?yàn)樯厦鍮lock未執(zhí)行,s值是nil
NSLog(@"11馬上訂閱消息");//2.第二步打印
[sig subscribeNext:^(id x) {//首次訂閱速和,上面的Block被執(zhí)行
NSLog(@"11接收到:%@",x); //Block里發(fā)送了消息歹垫,此處收到消息:aaa
}];
[s sendNext:@"ccc"]; //繼續(xù)發(fā)送,會(huì)導(dǎo)致前面的訂閱者收到消息:ccc
[s sendNext:@"ddd"]; //繼續(xù)發(fā)送颠放,會(huì)導(dǎo)致前面的訂閱者收到消息:ddd
[s sendNext:@"eeee"];//繼續(xù)發(fā)送,會(huì)導(dǎo)致前面的訂閱者收到消息:eeee
[sig subscribeNext:^(id x) {//再次訂閱不會(huì)導(dǎo)致訂閱代碼再次執(zhí)行
NSLog(@"222接收到:%@",x); //前面發(fā)送的消息全部能收到:aaa吭敢、ccc碰凶、ddd、eeee
}];
[s sendNext:@"ffff"];//繼續(xù)發(fā)送,會(huì)導(dǎo)致前面的兩個(gè)訂閱者都收到消息:ffff
控制臺(tái)打印結(jié)果如下圖: