🎏

CombineのSchedulerで実行時のキュー指定を理解するための図解

2020/10/26に公開

はじめに

CombineでPublisher - Subscriber 間でのSchedulerの役割について、ざっくりと整理してみます。間違いがあればコメントを頂ければと思います。

先に要約

まず先に結論

  • subscribe(on:options)
    • https://developer.apple.com/documentation/combine/record/subscribe(on:options:)
    • 雑な概要
      • 上流に影響し、結果的に下流にも影響する場合がある
      • Publisher動作に影響する
    • 仕様
      • 上流の実行コンテキストに影響する
        • 下流でSchedulerによるキューが指定されてなければ指定されていなければ下流にも影響する
      • Publisherがsubscribe, cancel, requestのオペレーション時にキューを指定する
  • receive(on:options)

WWDC19の図にScheduelrの実行タイミングを図示

上流とか下流に影響する、というルールで暗記するのではなく図によってタイミングを知っておけば理解が深まるんじゃないかと思ってます。

Apple公式リファレンスでの言及

先述の図に至る理屈をリファレンスから抜き出しておきます。

subscribe(on:options:)

リファレンスでは下記のように書かれています

Specifies the scheduler on which to perform subscribe, cancel, and request operations.

つまりこれは次のような意味でしょう

  • スケジューラの実行を指定するタイミングについては次の3つ
    • Publisherがsubscribeされたとき
    • Publisherがcancelされたとき
    • Publisehrがrequestされたとき

receive(on:options:)

リファレンスでは下記のように書かれています

Specifies the scheduler on which to receive elements from the publisher.

要素をPublisherから受信するスケジューラを指定する、ということなんで

  • Subscriberがreceiveしたときのタイミングは次の2つ
    • receive(_ input)のとき
    • receive(completion:)のとき

ちなみに下記に書かれているようにreceive(subscription:)時にはキューを指定しません。

Note
receive(on:options:) doesn’t affect the scheduler used to call the subscriber’s receive(subscription:) method.

これはおそらくですが、receive(subscription:)時にスケジューラをreceive(on:options)で指定してしまうと紛らわしいのと、意味がほぼないからだと感じます。

その他

言われなくてもわかってる人には必要ない話ですが、これ表面的な名前に騙されてはいけないってのが言いたいことです。というのも、subscribe(on:options:)がsink(サブスクライブ時)のスケジューラを決めるわけではないってことがわかったと思います。ただし、receive(on:options:)を指定しなければ切り替えられたスケジューラのまま実行は継続するため、結果sink時にも影響します。具体的にはsubscribe(on:options)してバックグラウンドスレッドで実行しても、それをメインスレッドに切り替えなければそのままってわけです。

さらにもう少し細かいことは下記で発表しました

https://speakerdeck.com/yimajo/sword-art-combine

Discussion