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 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。