麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

ReactiveCocoa比較區(qū)分replay,replayLast和replayLazily

2019-11-14 18:15:53
字體:
供稿:網(wǎng)友

    一直搞不明白replayLazily可以直接跳到最后看。

   原文:http://spin.atomicobject.com/2014/06/29/replay-replaylast-replaylazily/

  最近同事問我在ReactiveCoca中replay,replayLast和replayLazily有什么區(qū)別,但我對此也是一知半解,也不能完整描述出來它們之間的不同,所以,我將對它們進(jìn)行深入研究。

  如果你沒有對RACReplaySubject和RACMulticastConnection有很好的理解的話,你會對它們在頭文件中的描述理解的很困難。現(xiàn)在不去了解底層原理,我會嘗試去描述解析這些方法。

Subscribing to a Signal

  對于一個“普通”的信號,每次訂閱都將會導(dǎo)致信號中的代碼再執(zhí)行一遍,且該次訂閱者僅接收到該次訂閱發(fā)送出去的值。

  第一個例子演示每次訂閱都會重新執(zhí)行訂閱代碼。

__block int num = 0;  RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id  subscriber) {      num++;      NSLog(@"Increment num to: %i", num);      [subscriber sendNext:@(num)];      return nil;  }];   NSLog(@"Start subscriptions");   // Subscriber 1 (S1)  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   // Subscriber 2 (S2)  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   // Subscriber 3 (S3)  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];

  運(yùn)行結(jié)果如下:

Start subscriptions  Increment num to: 1  S1: 1  Increment num to: 2  S2: 2  Increment num to: 3  S3: 3

  可以看到,每次訂閱num都在遞增,如果不訂閱則不會遞增。通過這種方式,可以知道信號是懶惰的,如果沒有訂閱者的話,是不會執(zhí)行的。

  第二個例子演示信號被添加訂閱的時候,訂閱者是怎么接收發(fā)送的值的。

 RACSubject *letters = [RACSubject subject];  RACSignal *signal = letters;   NSLog(@"Subscribe S1");  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   NSLog(@"Send A");  [letters sendNext:@"A"];  NSLog(@"Send B");  [letters sendNext:@"B"];   NSLog(@"Subscribe S2");   [signal subscribeNext:^(id x) {       NSLog(@"S2: %@", x);  }];   NSLog(@"Send C");  [letters sendNext:@"C"];  NSLog(@"Send D");  [letters sendNext:@"D"];   NSLog(@"Subscribe S3");  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];

運(yùn)行結(jié)果

Subscribe S1 Send AS1: A Send BS1: B Subscribe S2 Send CS1: CS2: C Send DS1: DS2: D Subscribe S3

  在很多情況下,這是我們想要的預(yù)期結(jié)果,不過在某些情況下,你不需要訂閱的代碼再次被執(zhí)行。例如訂閱 一個向網(wǎng)絡(luò)服務(wù)器發(fā)送的請求,當(dāng)服務(wù)器返回數(shù)據(jù)時,多個監(jiān)聽者需要更新(無論有多少個監(jiān)聽者,請求只發(fā)送一下(第一個例子就不滿足我們的需求)),或者我們想拿到訂閱前信號發(fā)送過的值(第二個例子,S2想拿A,B的值或者S3想拿A,B,C,D的值,就不滿足我們的需求了)。因此-replay-replayLast, and -replayLazily應(yīng)需而生。

Subscribing to a -replay Signal

  這個replay方法將返回一個新的信號,當(dāng)源信號被訂閱時,會立即發(fā)送給訂閱者全部歷史的值,不會重復(fù)執(zhí)行源信號中的訂閱代碼,不僅如此,訂閱者還將收到所有未來發(fā)送過去的值。

  第一個例子演示信號添加新的訂閱時,代碼是不會再次被執(zhí)行的。

__block int num = 0;  RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id  subscriber) {      num++;      NSLog(@"Increment num to: %i", num);      [subscriber sendNext:@(num)];      return nil;  }] replay];   NSLog(@"Start subscriptions");   // Subscriber 1 (S1)  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   // Subscriber 2 (S2)  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   // Subscriber 3 (S3)  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];
Increment num to: 1  Start subscriptions  S1: 1  S2: 1  S3: 1

  信號首次被訂閱時,num立馬被遞增了,且僅僅遞增了一次。這說明了不管有你多個訂閱者,訂閱代碼我只執(zhí)行了一次。

  

  第二個例子演示每個新添加的訂閱者接收到信號中全部的值(不管是之前發(fā)出的值還是將來發(fā)出的值)。

  

RACSubject *letters = [RACSubject subject];  RACSignal *signal = [letters replay];   NSLog(@"Subscribe S1");  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   NSLog(@"Send A");  [letters sendNext:@"A"];  NSLog(@"Send B");  [letters sendNext:@"B"];   NSLog(@"Subscribe S2");  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   NSLog(@"Send C");  [letters sendNext:@"C"];  NSLog(@"Send D");  [letters sendNext:@"D"];   NSLog(@"Subscribe S3");  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];
Subscribe S1    Send A   S1: A Send BS1: B Subscribe S2S2: AS2: B Send CS1: CS2: C Send DS1: DS2: D Subscribe S3S3: AS3: BS3: CS3: D

  盡管訂閱者S3在所有的值發(fā)送之后再訂閱,然后還能接收到所有的值。

Subscribing to a -replayLast Signal

  這個replayLast返回一個新的信號,當(dāng)源信號被訂閱時,會立即發(fā)送給訂閱者最新的值,不會重復(fù)執(zhí)行源信號中的訂閱代碼。訂閱者還會收到信號未來所有的值。

  對于第一個例子,跟之前replay一樣,所以我就不再次演示了。

  第二個例子演示如何將最新的值提供給新的訂閱者

RACSubject *letters = [RACSubject subject];  RACSignal *signal = [letters replayLast];   NSLog(@"Subscribe S1");  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   NSLog(@"Send A");  [letters sendNext:@"A"];  NSLog(@"Send B");  [letters sendNext:@"B"];   NSLog(@"Subscribe S2");  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   NSLog(@"Send C");  [letters sendNext:@"C"];  NSLog(@"Send D");  [letters sendNext:@"D"];   NSLog(@"Subscribe S3");  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];
Subscribe S1 Send AS1: A Send BS1: B Subscribe S2S2: B Send CS1: CS2: C Send DS1: DS2: D Subscribe S3S3: D

Subscribing to a -replayLazily Signal

  這replayLazily方法返回一個新的信號,當(dāng)源信號被訂閱時,會立即發(fā)送給訂閱者全部歷史的值,不會重復(fù)執(zhí)行源信號中的訂閱代碼。跟replay不同的是,replayLazily被訂閱生成新的信號之前是不會對源信號進(jìn)行訂閱的(原文寫的有點(diǎn)繞,簡單來講 直到訂閱時候才真正創(chuàng)建一個信號,源信號的訂閱代碼才開始執(zhí)行)。暫時不理解也沒事,看下面的代碼輸出,和注釋。

 這第一個例子會說明跟replay差異。 注意字符串 “Increment num to: 1”是被訂閱了之后才打印顯示的。而replay和replayLast沒被訂閱前就打印了“Increment num to: 1” 這個消息。

__block int num = 0;  RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id  subscriber) {      num++;      NSLog(@"Increment num to: %i", num);      [subscriber sendNext:@(num)];      return nil;  }] replayLazily];  //跟replay不同的就這么一個地方   NSLog(@"Start subscriptions");   // Subscriber 1 (S1)  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   // Subscriber 2 (S2)  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   // Subscriber 3 (S3)  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];
// 帖子滾動起來,跟replay比較一下 Increment num to: 1 的顯示順序。Start subscriptions     // 實(shí)際訂閱Increment num to: 1 // 信號開始創(chuàng)建S1: 1S2: 1S3: 1

 

  第二個例子演示將全部歷史的值提供給任何新的訂閱者,就像replay一樣。

RACSubject *letters = [RACSubject subject];  RACSignal *signal = [letters replayLazily];   NSLog(@"Subscribe S1");  [signal subscribeNext:^(id x) {      NSLog(@"S1: %@", x);  }];   NSLog(@"Send A");  [letters sendNext:@"A"];  NSLog(@"Send B");  [letters sendNext:@"B"];   NSLog(@"Subscribe S2");  [signal subscribeNext:^(id x) {      NSLog(@"S2: %@", x);  }];   NSLog(@"Send C");  [letters sendNext:@"C"];  NSLog(@"Send D");  [letters sendNext:@"D"];   NSLog(@"Subscribe S3");  [signal subscribeNext:^(id x) {      NSLog(@"S3: %@", x);  }];
Subscribe S1 Send AS1: A Send BS1: B Subscribe S2S2: AS2: B Send CS1: CS2: C Send DS1: DS2: D Subscribe S3S3: AS3: BS3: CS3: D

  總結(jié)一下:

  ReactiveCocoa提供了這三個簡便的方法允許多個訂閱者訂閱一個信號,卻不會重復(fù)執(zhí)行訂閱代碼,并且能給新加的訂閱者提供訂閱前的值。replay和replayLast使信號變成熱信號,且會提供所有值(-replay) 或者最新的值(-replayLast) 給訂閱者。 replayLazily返回一個冷的信號,會提供所有的值給訂閱者。

 


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 水卜樱一区二区av | av成人在线播放 | 亚洲第五色综合网 | 亚洲精品永久视频 | 黄色午夜剧场 | 亚洲婷婷日日综合婷婷噜噜噜 | 港台三级在线观看 | 国产精品久久久久久久午夜片 | 制服丝袜日日夜夜 | 久久国产精品二国产精品中国洋人 | 久久精品日产高清版的功能介绍 | 欧美日本一区二区 | xnxx 日本19| 毛片在线免费观看网址 | 999久久久国产999久久久 | 成人在线免费观看网址 | 成人一区二区三区在线 | 性生活视频一级 | 在线成人免费观看www | 欧美成人一区免费视频 | 少妇一级淫片免费放正片 | 黄色7777| 亚洲天堂午夜 | 狠狠操精品视频 | 日韩字幕| 黄视频免费在线观看 | 久久精品日韩一区 | 爱福利视频 | 精品久久久久久久久久中文字幕 | 在线观看福利网站 | 亚洲精品一区中文字幕 | 永久免费av在线 | 少妇的肉体k8经典 | 日韩在线欧美在线 | 欧美国产精品久久 | 深夜毛片免费看 | 欧美激情在线播放 | 久久久久亚洲a | 日韩 综合 | 91久久一区| 男女羞羞的视频 |