スケジューラーとスレッド処理
receive(on:)とsubscribe(on:)で実行を制御します。
「スケジューラーとスレッド処理」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
Combineのスケジューラ
Combineのスケジューラは、処理をいつ、どこで実行するかを定義します。つまり、どのスレッドまたはキューで演算子を実行し、購読者へ値を配信するかを決めます。
UIの更新をメインスレッドで行い、負荷の高い処理をメインスレッド以外で実行するには、スケジューラの制御が不可欠です。
2つの重要な演算子
Combineには、スレッド処理を制御する2つの演算子があります。
- subscribe(on:) — 購読と上流の処理を開始する場所を制御する
- receive(on:) — 下流の値が配信される場所を制御する
これらはパイプラインの異なる側に影響します。
receive(on:)
receive(on:)は、その後のすべての処理を指定したスケジューラ上へ移します。最も一般的な用途は、UIを更新する前にメインキューへ戻ることです。
apiClient.fetchUser(id: 1)
.receive(on: DispatchQueue.main)
.sink { user in
self.nameLabel.text = user.name
}
.store(in: &cancellables)subscribe(on:)
subscribe(on:)は、パブリッシャーが生成を開始するスレッドと、上流の演算子が実行される場所を制御します。負荷の高い初期化処理をメインスレッドから移すために使用します。
heavyPublisher
.subscribe(on: DispatchQueue.global(qos: .userInitiated))
.receive(on: DispatchQueue.main)
.sink { result in
self.update(result)
}
.store(in: &cancellables)subscribe(on:)とreceive(on:)の比較
方向を覚えておきましょう。
- subscribe(on:)は上流に影響する — 処理を開始する場所
- receive(on:)は下流に影響する — 結果が配信される場所
一般的なパターンでは、バックグラウンド処理にsubscribe(on:)を、メインスレッドへの配信にreceive(on:)を使用します。
スケジューラとしてのDispatchQueue
DispatchQueueはSchedulerプロトコルに準拠しています。DispatchQueue.mainはメインスレッドで配信し、グローバルキューはバックグラウンドで並行して実行します。
let background = DispatchQueue.global(qos: .background)
publisher
.map { expensiveTransform($0) }
.subscribe(on: background)
.receive(on: DispatchQueue.main)
.sink { self.render($0) }
.store(in: &cancellables)スケジューラとしてのRunLoop
RunLoopは、スレッドのランループに関連付けられた別のスケジューラです。RunLoop.mainはUIイベントと連携して配信するため、スクロールの応答性などに影響する場合があります。
timerPublisher
.receive(on: RunLoop.main)
.sink { _ in
self.tick()
}
.store(in: &cancellables)DispatchQueueとRunLoopの比較
どちらもメインスレッドで配信できますが、微妙な違いがあります。
- DispatchQueue.main — スクロール中のトラッキング中でもスケジュールする
- RunLoop.main — ランループがトラッキングモードの間は処理を遅延させる
非同期処理の後に行うほとんどのUI更新では、DispatchQueue.mainをデフォルトとして使用するほうが安全です。
スケジューラを使うタイミング演算子
debounce、throttle、delayなどの演算子は、タイミング処理をどのキューで行うかを決めるスケジューラ引数を受け取ります。
searchTextPublisher
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
.sink { query in
self.runSearch(query)
}
.store(in: &cancellables)よくあるスレッド処理のバグ
メインスレッド以外でUIを更新すると、クラッシュや表示の不具合が発生します。バックグラウンドのパブリッシャーの後にreceive(on: DispatchQueue.main)を記述し忘れると、sinkがバックグラウンドスレッドで実行される可能性があります。
UIに渡す値は、必ずメインスケジューラで配信してください。
全体を組み合わせる
堅牢なパイプラインはバックグラウンドで処理を開始し、そこで処理を行った後、表示のためにメインスレッドへ値を配信します。
imageURLPublisher
.subscribe(on: DispatchQueue.global())
.flatMap { url in downloadImage(url) }
.map { resize($0) }
.receive(on: DispatchQueue.main)
.sink { self.imageView.image = $0 }
.store(in: &cancellables)理解度チェック
スケジューラについての知識を確認しましょう。
まとめ
Combineでスレッド処理を制御する方法を学びました。
- subscribe(on:) — 上流の処理を開始する場所
- receive(on:) — 結果が配信される場所
- スケジューラとしてのDispatchQueueとRunLoop
- UIの更新は必ずメインスレッドで配信する
適切なスケジューリングによって、アプリの応答性を保ち、クラッシュを防げます。
よくある質問
「スケジューラーとスレッド処理」レッスンは無料ですか?
はい。「スケジューラーとスレッド処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「スケジューラーとスレッド処理」で何を学びますか?
receive(on:)とsubscribe(on:)で実行を制御します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「スケジューラーとスレッド処理」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ストリームの変換と結合
- スケジューラーとスレッド処理
- エラー処理演算子
- カスタムPublisherとSubscriber