RxSwiftのMainSchedulerは何物か

遅まきながら、RxSwiftに手を付け始めました。

github.com

リアクティブプログラミングはまったく経験がないので、公式の「Getting Started」を読みながら、概念や基本を調べることにします。

ですが、まだ分からないことばかりで詳細には全然立入れていません。

オブザーバとジェネレータ

リアクティブプログラミングには「オブザーバ」と「ジェネレータ」の2つのキーワードがあるようです。このEquivalenceを理解することがRxホニャララを理解する上でもっとも重要なのだそう。

このページの記述を引用すると、それぞれは次のようにプッシュ型かプル型かで使い分けるとのこと。

  • Push interface - Observer (observed elements over time make a sequence)
  • Pull interface - Iterator / Enumerator / Generator

まだよく分からず。

スケジューラ

Rxは非同期(asynchronous)で動いているので、処理をどのスケジューラ(スレッド)で動かすかを指定しなければいけません。この点はGCDと同じです。 Getting Startedの中では、「Dispose」の節にてはじめてソースコードが登場し、Observable<SignedIntegerType>interval()メソッドが持つschedulerなる引数で、スケジューラを指定しています。

let subscription = Observable<Int>.interval(0.3, scheduler: scheduler)
    .subscribe { event in
        print(event)
    }

NSThread.sleepForTimeInterval(2)

subscription.dispose()

これは0.3秒ごとに2秒になるまで(つまり合計6回)eventオブジェクトをコンソールに出力し続ける処理ですが、schedulerとして突然出てきている変数があります。これが処理実行のスレッドとして使われるようです。ただ、このコードだけを記述してもschedulerが未定義になってエラーになるので、何かきちんとしたインスタンスを指定する必要があります。メソッドの型宣言ではSchedulerType型のインスタンスが使えるとのこと。

何を指定するのかなとGetting Startedをもう少し先に進んでみたところ、同様の処理で「MainScheduler.instance」と書いてある箇所がありました。試しにこれを使ってみたところ、エラーなく実行できるようになりました。何者なのか、MainSchedulerの中身を見てみます。

public final class MainScheduler : SerialDispatchQueueScheduler {

    private let _mainQueue: dispatch_queue_t

    var numberEnqueued: AtomicInt = 0

    private init() {
        _mainQueue = dispatch_get_main_queue()
        super.init(serialQueue: _mainQueue)
    }

    /**
    Singleton instance of `MainScheduler`
    */
    public static let instance = MainScheduler()
    :

まだ処理の詳細は追えないものの、dispatch_get_main_queue()を使っていることから、メインスレッドが使われると考えて良さそうです。

時間切れになったので、今回はここまで。

今回のまとめ

  • MainScheduler.instanceは、MainSchedulerオブジェクトをインスタンス化して返している。このスケジューラはメインスレッドを使用している
    • てことはUI変更も処理の中で行えるのですね
  • Rx、用語やAPIを多く覚えないと使いこなせなさそう