もちゅるの日常

特に決まっていないざっくばらんなブログ

RxSwift Scheduler(スケジューラ)の一覧と使い方

RxSwiftを使っていると必ず出てくるScheduler(スケジューラー)ですが、どんな種類があるのか把握できずに使っていました。

このままだと実装の自由度が変わらずでもったいないので、一覧と使い方を少し調べてみることにしました。

なおここで提案している使い方が答えと思わず参考程度にすることをオススメします。

使い方は1つではないですもんね。

Scheduler(スケジューラ)とは?

そもそも分からない人に超絶ざっくり説明すると、Schedulerとはスレッド制御とまずは覚えておいて、のちのち慣れてきてから詳しく知る順番でいいと思います。

Scheduler(スケジューラ)一覧

  • MainScheduler
  • ConcurrentMainScheduler
  • SerialDispatchQueueScheduler
  • ConcurrentDispatchQueueScheduler
  • OperationQueueScheduler
  • CurrentThreadScheduler
  • ImmediateScheduler
  • HistoricalSchedulerTimeConverter
  • VirtualTimeScheduler

MainScheduler

メインスレッドで実行するSchedulerです。 observeOnに最適化されておりメインスレッドを指定します。 MainScheduler.instance を渡して使います。 スケジュールするメソッドがメインスレッド上であれば即時実行されます。 MainScheduler.asyncInstanceは後述するSerialDispatchQueueSchedulerを参照ください。

ConcurrentMainScheduler

メインスレッドで実行するSchedulerです。 subscribeOnに最適化されておりメインスレッドを指定します。 スケジュールするメソッドがメインスレッド上であれば即時実行されます。

SerialDispatchQueueScheduler

バックグラウンドで処理を順次実行するのに使います。 内部でシリアルキューを保持しており、並列キューを渡してもシリアル実行されます。

ConcurrentDispatchQueueScheduler

バックグラウンドで処理を並列実行するのに使います。 GCD のdispatch_queue_tQOSで指定します。

OperationQueueScheduler

NSOperationQueueを使った非同期実行をします。 同時実行数を制御できるのが便利なところ.

CurrentThreadScheduler

現在のスレッドを指定します。 処理を一度キューイングしてから実行します。

ImmediateScheduler

現在のスレッドを指定します。 処理をキューイングせず即時実行します。

HistoricalSchedulerTimeConverter

時間経過を制御できるSchedulerです。 n秒後に実行などのテストで便利かと思います。

VirtualTimeScheduler

時間経過をプログラムで制御するSchedulerです。 受け取った時間を何軸の時間に扱うかなどを制御を実装して使います。 テストとして使えますが、HistoricalSchedulerを使ったり、ライブラリ側がテストスケジューラを提供したりと、あまり使う機会はないかと思います。

まとめ

通常であればMainScheduler,ConcurrentDispatchQueueSchedulerをよく使いますが、 CurrentThreadSchedulerImmediateSchedulerを理解できていると実装が楽になるケースとかありそうですね。

背景色をグラデーション

UIViewにはCALayerといったレイヤー機能を持っているので、このレイヤーにグラデーション用レイヤーを追加します。
なおグラデーションレイヤーを使うには QuartzCore フレームワークの追加とヘッダーのインポートを忘れずに。

    // 背景色を初期化
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = [UIScreen mainScreen].bounds;
    gradient.colors = @[ (id)[[UIColor whiteColor] CGColor], (id)[[UIColor darkGrayColor] CGColor] ];
    [self.view.layer insertSublayer:gradient atIndex:0];

日時の差を求める

NSDateComponents を使って「ある日」と「とある日」の差を算出します。

NSDate* date1 = ある日;
NSDate* date2 = とある日;
NSCalendar* calendar = [NSCalendar currentCalendar];
NSUInteger flags = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit;
NSDateComponents *diff = [calendar components:flags fromDate:date1 toDate:date2 options:0];
NSLog(@"Day: %d Hour: %d Minute: %d", [diff day], [diff hour], [diff minute]);

NSDateComponents.dateでnilが返される

NSDateComponentsでNSDate形式が欲しい時にdateがあるので使おうとしたところnilが帰ってきた時のメモ

    NSDateComponents* dc = [[NSDateComponents alloc] init];
    [dc setCalendar:[NSCalendar currentCalendar]];

予めカレンダーをセットすればよさげ