ReactiveCocoa。 並行性。 マルチスレッド

今日は、ReactiveCocoaでスレッドを操作することについてお話ししたいと思います。 フレームワークの詳細については説明しませんが、iOSでのリアクティブプログラミングの基本原則は既にご存じだと思います。





モバイルアプリケーションでストリームを操作することは最も重要なトピックであり、誰もがこれを知っています。 このための標準ツールはGCDまたはNSOperationです。 しかし、プロジェクトでReactiveCocoaを使用すると、すべてが少し異なります。 いいえ、標準ツールの使用を禁止する人はいませんが、なぜですか? 各ブロックにGCDを押し込みますか? これを行うために、ReactiveCocoaは非常に便利な実装を思い付きました。



ReactiveCocoaでマルチスレッドを使用する場合、クラスRACSchedulerがあります。 本質的に、これはGCDのラッパーであり、GCDと同じスレッド優先順位を持ちます。

typedef enum : long { RACSchedulerPriorityHigh = DISPATCH_QUEUE_PRIORITY_HIGH, RACSchedulerPriorityDefault = DISPATCH_QUEUE_PRIORITY_DEFAULT, RACSchedulerPriorityLow = DISPATCH_QUEUE_PRIORITY_LOW, RACSchedulerPriorityBackground = DISPATCH_QUEUE_PRIORITY_BACKGROUND, } RACSchedulerPriority;
      
      







基本的なRACSchedulerメソッドを使用するときに必要になる可能性があることを考慮してください。



名前から、原則として、メインスレッドで作業を実行するRACSchedulerに戻ることが明らかになります。

 + (RACScheduler *)mainThreadScheduler;
      
      





この場合、示された優先度のRACSChedulerが返され、メインスレッドに存在しなくなります。

 + (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority;
      
      





優先度がRACSchedulerPriorityDefaultのRACSchedulerを返します。

 + (RACScheduler *)scheduler;
      
      





現在のNSThreadから現在のRACSchedulerを返します。

 + (RACScheduler *)currentScheduler;
      
      





RACShedulerがどこでも実行できるブロック。 そして、これに戻ります。

 - (RACDisposable *)schedule:(void (^)(void))block;
      
      







以下は、マルチスレッドの管理に使用できるRACSignalの主要な機能です。

このRACSignalメソッドは、subscribeNext / doNext / subscribeError /などで新しい値を取得するためのブロックであると言います。 RACSChedulerで実行され、返金されます。

 - (RACSignal *)deliverOn:(RACScheduler *)scheduler
      
      





このRACSignalメソッドは、サブスクリプションの作成時に作成されたブロックがどのRACSchedulerで実行されるかを示します(ReactiveCocoa 2.5の場合、これは次のとおりです。+ [RACSignal createSignal:])

 - (RACSignal *)subscribeOn:(RACScheduler *)scheduler
      
      







2つの短い例を挙げて、ここで終わります。



簡単な信号を作成しましょう:

 RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) { // block executes on other thread with default priority for (NSInteger i = 0; i < 5000; i++) { NSLog(@"LOL"); if (i == 5000) { [subscriber sendNext:@(YES)]; } } return nil; }];
      
      







明らかに、このシグナルのサブスクリプションを作成するとき、サイクルが終了するまで、単一の値を取得しません。 誰かにとって、このブロックで実行されるコードはかなりリソースを消費します。 スレッドで拡散してみましょう。



シグナルサブスクリプションを作成し、シグナルsubscribeOn / deliverOnをポイントします

 [[[signal subscribeOn:[RACScheduler scheduler]] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { // block executes on main thread }];
      
      







この場合、コメントからわかるように、メインスレッドで値を取得します。たとえば、UIを更新できます。 サブスクリプションを作成するためのブロックでは、コードは別のスレッドで実行され、メインスレッドの負荷を軽減します。



最後の例では、メインストリームのバックグラウンドストリームからコードを実行する方法を示します。

GCDでは、次のように誰もがすでに知っているように見えます。

 dispatch_async(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^{ // do something dispatch_async(dispatch_get_main_queue(), ^{ // do something }); });
      
      







そして、これをRACSchedulerでどのように実装できますか?

思い出してくださいが、このシグナルのサブスクリプションを作成するとき、メインスレッドで実行されないことを示しました。 しかし、ある場所で、すべてがメインスレッドでコードの一部を実行する必要がある場合はどうでしょうか。 非常に簡単です:)ここでそれは私たちを助けます-(RACDisposable *)スケジュール:(void(^)(void))ブロック;



 RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) { // block executes on other thread with default priority for (NSInteger i = 0; i < 5000; i++) { NSLog(@"LOL"); if (i == 5000) { [subscriber sendNext:@(YES)]; } } [[RACScheduler mainThreadScheduler] schedule:^(void v) { // do something on main thread }]; return nil; }];
      
      






All Articles