ReactiveCocoaはreplay、replayLastとreplay Lazillyを比較的に区別します。

14501 ワード

replay Lazilyとreplayの違いがよく分かりません。直接最後までジャンプしてみてください。
  原文:http://spin.atomicobject.com/2014/06/29/replay-replaylast-replaylazily/
  
RACReplaySubjectとRACMulticastConnectionについて深く研究していないと、ヘッダファイルの記述を理解するのは難しいです。今は下の原理を理解しないで、分かりやすい言語とグラフでこれらの方法を説明します。
 
Subscribing to a Signal
1つの「普通」の信号については、定期購読のたびに信号のコードが再実行され、この購読者はこの購読で送信された値だけを受信する。
最初の例は、購読するたびに購読コードを再実行することを示します。
__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);
  }];
運転結果は以下の通りです。
Start subscriptions
  Increment num to: 1
  S1: 1
  Increment num to: 2
  S2: 2
  Increment num to: 3
  S3: 3
定期購読の度にnumが増加し、購読しないと増加しないことが分かります。このようにして、信号が怠け者であることが分かります。もし予約者がいなかったら、実行しません。
第二の例では、デモ信号に購読が追加された場合、購読者はどのように送信値を受信しますか?
 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);
  }];
実行結果
Subscribe S1
 
Send A
S1: A
 
Send B
S1: B
 
Subscribe S2
 
Send C
S1: C
S2: C
 
Send D
S1: D
S2: D
 
Subscribe S3
多くの場合、これは私たちが望む結果ですが、場合によっては、購読コードが再実行される必要はありません。例えば、ネットワークサーバに送信する要求を購読し、サーバがデータを返すと、複数の傍受者が更新する必要がある(いくつかの傍受者がいても、一度だけ送信してほしい(第一の例は私たちの要求を満たしていない)。(第二の例では、S 2はA、Bの値、またはS 3はA、B、C、Dの値を取りたいので、私たちの需要を満たしていません。)  -replay、and  -replayLastSubscribing to a-replay Signal
このreplay方法は、ソース信号が購読されると、購読者の履歴のすべての値にすぐに送信されます。ソース信号の購読コードは重複して実行されません。これだけではなく、購読者は未来のすべての過去の値を受信します。
最初の例のデモ信号に新しい購読を追加した場合、コードは再実行されません。
__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はすぐに増分されました。一回だけ増加しました。これはあなたが多くの購読者がいても、購読コードは一回だけ実行しました。
  
第二の例は、新たに追加された各購読者が信号中のすべての値を受信することを示している。
  
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 B
S1: B
 
Subscribe S2
S2: A
S2: B
 
Send C
S1: C
S2: C
 
Send D
S1: D
S2: D
 
Subscribe S3
S3: A
S3: B
S3: C
S3: D
購読者S 3は、すべての値を送信してから購読しても、すべての値を受信することができる。
Subscribing to a-replayLast Signal
このreplayLastは、ソース信号が購読されると、すぐに購読者に最新の値を送ります。ソース信号の購読コードは繰り返し実行されません。購読者は信号の将来のすべての値を受信します。
最初の例については、前回のレプレーと同じですので、もう二度とプレゼンテーションしません。
第二の例はどのように最新の値を新しい購読者に提供するかを示します。
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 A
S1: A
 
Send B
S1: B
 
Subscribe S2
S2: B
 
Send C
S1: C
S2: C
 
Send D
S1: D
S2: D
 
Subscribe S3
S3: D
Subscribing to a-replay Lazinly Signal
このreplayLazily方法は、ソース信号が購読された時に、すぐに購読者の歴史のすべての値に送信されます。ソース信号の購読コードは繰り返し実行されません。replay Lazuiは、購読されて新しい信号を生成する前に、ソース信号を購読しません。(原文の書き方は回りくどいです。簡単に言うと、購読時に信号が本当に作成され、ソース信号の購読コードが実行されます。)しばらくは理解しなくても大丈夫です。下のコード出力とコメントを見てください。
この最初の例はreplayとの違いを説明します。文字列に注意してください。 「Increment num to:1」は購読されてから印刷されて表示されますが、replayとreplay Lastは購読されていない前に「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     //     
Increment num to: 1 //       
S1: 1
S2: 1
S3: 1
 
第二の例のデモは、すべての歴史の値を任意の新しい購読者に提供し、リプレイと同じです。
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 A
S1: A
 
Send B
S1: B
 
Subscribe S2
S2: A
S2: B
 
Send C
S1: C
S2: C
 
Send D
S1: D
S2: D
 
Subscribe S3
S3: A
S3: B
S3: C
S3: D
まとめてみます。
ReactiveCocoaは、この3つの簡便な方法で複数の購読者が1つの信号を購読することができますが、購読コードを繰り返し実行することなく、新たに追加された購読者に購読前の値を提供します。replayLastは信号をホット信号に変えて、すべての値(-replayLazily 。)または最新の値(-replay)を購読者に提供します。 replayLazlyは冷たい信号を返して、すべての値を購読者に提供します。