RACSequence
とRACStream
は3.0でDeprecateになる予定になっており、
コレクション周りの処理を行いたければ、Underscore.mやRXCollectionsなどのサードパーティライブラリを使ってね、ということになりました (ちなみに、現時点でのReactiveCocoaの安定版は2.0なので、3.0は開発版です)。
これによって、RACSequence
とRACStream
にあったメソッドがRACSignal
に移動して、コードも非常にわかりやすくなりました。
今回はその例として、concat:
とcatch:
のコードを見てみます。
concat:
とcatchTo:
の動作について
簡単に言うと、concat:
とcatchTo:
はどちらも2つのシグナルをくっつけてひとつのシグナルに見せかけます。
そのくっつける条件が異なっていて、レシーバであるシグナルオブジェクトが、CompletedとErrorのどちらのイベントで終わるかで決まります。
concat:
はレシーバがCompletedイベントで終わるなら、くっつけるcatchTo:
はレシーバがErrorイベントで終わるなら、くっつける
具体的な例で見てみましょう。例えば、次の3つのシグナルがあったとします。
- シグナル
AC
はnextイベントx
とnextイベントy
を送信したあとに、Completedイベントで終わる (これをAC
::=
x
→y
→ Completedと表すことにします) - シグナル
AE
::=
x
→y
→ Error - シグナル
B
::=
z
→ Completed
このとき、これらをconcat:
とcatchTo:
で結合したシグナルは、それぞれ次のような結果が得られます。
[AC concat:B]
::=
x
→y
→z
→ Completed[AE concat:B]
::=
x
→y
→ Error[AC catchTo:B]
::=
x
→y
→ Completed[AE catchTo:B]
::=
x
→y
→z
→ Completed
コード
ではコードを見ていきましょう。なお、以下のコードでは説明に不要な個所はオリジナルコードから省いています。
concat:
最初5行くらいは無視して、next:
あたりからのコードに注目してください。
- (RACSignal *)concat:(RACSignal *)signal { return [RACSignal create:^(id<RACSubscriber> subscriber) { [self subscribeSavingDisposable:^(RACDisposable *disposable) { [subscriber.disposable addDisposable:disposable]; } next:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ [signal subscribe:subscriber]; }]; }]; }
nextイベントとerrorイベントはただ転送しているだけですが、completedイベントについては、引数のシグナルに繋げていることがわかります。
catch:
このメソッドは上のconcat:
と似ていることに気付いたでしょうか? 違う点は引数の型がblockになっていることと、
errorイベントとcompletedイベントあたりの処理がconcat:
とは逆になっていることです。
- (RACSignal *)catch:(RACSignal * (^)(NSError *error))catchBlock { return [RACSignal create:^(id<RACSubscriber> subscriber) { [self subscribeSavingDisposable:^(RACDisposable *disposable) { [subscriber.disposable addDisposable:disposable]; } next:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { RACSignal *signal = catchBlock(error); [signal subscribe:subscriber]; } completed:^{ [subscriber sendCompleted]; }]; }]; }
catch:
では、nextイベントとcompletedイベントはただ転送しているだけですが、errorイベントについては、引数のblockが生成するシグナルに繋げていることがわかります。
最初の説明に出てきていたcatchTo:
は、このcatch:
を使って実現されています。
catchTo:
このコードはReactiveCocoa 2.0と同じです。
- (RACSignal *)catchTo:(RACSignal *)signal { return [self catch:^(NSError *error) { return signal; }]; }
おわりに
ReactiveCocoa 3.0のconcat:
とcatch:
のコードを簡単に紹介しました。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。