OperationQueueは、Grand Central Dispatch上に構築されたiOSおよびmacOSの高レベルタスクキューです。Apple Developer Documentation、2026によると、OperationQueueはOperationのインスタンス(作業単位をカプセル化するオブジェクト)を管理します。DispatchQueueとは異なり、OperationQueueは操作間の依存関係、優先順位、KVO監視、実行中のタスクのキャンセルをサポートします。OperationQueueはスレッドプールを自動的に管理し、システムの利用可能なリソース全体に操作を分散します。
重要なポイント
OperationQueueはFoundationフレームワークのクラスで、Operationオブジェクトの実行を管理します。DispatchQueueとは異なり、OperationQueueはシリアルモードかコンカレントモードかを明示的に指定する必要はありません。同時に実行される操作の数はmaxConcurrentOperationCountプロパティによって制御されます。値1はキューを順次実行にし、その他の値はコンカレントにします。
Operationは作業単位を表す抽象クラスです。各操作には状態があります:ready、executing、finished、cancelled。これらの状態はKVO(キー値監視)と互換性があり、変更に反応できます(例:操作完了時にUIを更新する)。OperationはisExecutingフラグとisFinishedフラグを自動的に管理します。
Apple(2026)によると、OperationQueueは内部的にGCDを使用しますが、DispatchQueueでは利用できない機能を追加します:操作の依存関係、優先順位、キャンセル。アプリがバックグラウンドに入ると、OperationQueueは実行を一時停止し、復帰時に再開します。OperationQueueはCPUコア数も自動的に考慮し、最適なスレッド数を選択します。
各操作は4つの状態を経ます:pending(保留中)、ready(準備完了)、executing(実行中)、finished(完了)。cancelled状態は完了前のどの段階でも発生する可能性があります。状態遷移はKVOを通じて追跡されます—これがリアクティブなUI更新の基盤です。OperationQueueは完了した操作を自動的にキューから削除し、依存する操作に前提条件が満たされたことを通知して実行を開始します。
Operationは抽象クラスであり、main()またはstart()メソッドのオーバーライドが必要です。タスクコードはmain()メソッドに配置され、isExecutingとisFinishedの状態は自動的に管理されます。非同期操作の場合は、start()をオーバーライドし、状態フラグを手動で管理する必要があります。
BlockOperationはOperationの具象実装で、1つ以上のコードブロックを実行します。addExecutionBlock()を通じて複数のブロックを追加すると、BlockOperationはコンカレントになります。操作は追加されたすべてのブロックが実行された後にのみ完了します。BlockOperationは継承なしで単純なタスクに便利な代替手段です。
| 特性 | Operation | BlockOperation |
|---|---|---|
| クラスタイプ | 抽象 | 具象 |
| 継承 | 必要 | 不要 |
| 非同期性 | 手動KVO管理 | 自動 |
| コードブロック | main()に1つ | 1つまたは複数 |
| 使用法 | 状態を持つ複雑なタスク | 単純な1回限りのタスク |
| 適している用途 | 依存関係、キャンセル、進捗 | クイックブロック、完了処理 |
| メモリ | KVOと状態により高い | 最小限、軽量 |
カスタム操作を作成するには、Operationをサブクラス化し、main()をオーバーライドします。内部で、コストのかかる操作の前にisCancelledフラグをチェックして、迅速なキャンセルを確保します。これは大きなファイルのダウンロードやバッチデータ処理に重要です。OperationとBlockOperationの選択はタスクの複雑さに依存します:単純な1回限りのアクションにはBlockOperationで十分です。状態を持つ再利用可能なロジックにはOperationをサブクラス化します。
依存関係は、DispatchQueueに対するOperationQueueの主要な利点です。addDependency(_:)メソッドは、操作Bが操作Aの完了後にのみ実行されることを指定します。依存関係は有向非巡回グラフ(DAG)を形成します:循環依存関係が追加されると、キューはそれを無視し、操作は開始されません。
操作の優先順位は、queuePriorityプロパティを通じて値(.veryLow、.low、.normal、.high、.veryHigh)で設定されます。優先順位は準備完了した操作間の開始順序に影響しますが、依存関係を上書きしません。OperationQueueは最初に依存関係を解決し、次に利用可能な操作間で優先順位を適用します。
典型的なシナリオはプロファイルデータの読み込みです:最初にユーザーを読み込み、次にそのIDに基づいて友達と投稿を読み込みます。ユーザーの読み込みと友達の読み込みの間に依存関係を設定すると、ネストされた完了ハンドラなしで正しい順序が保証されます。
maxConcurrentOperationCountプロパティは、同時に実行される操作の数を制限します。値1は順次キューを作成し、デフォルト値(NSOperationQueueDefaultMaxConcurrentOperationCount)はシステム最適で、現在のデバイス負荷に依存します。このパラメータの適切な設定は過剰なリソース消費を防ぎます:画像読み込みには4〜6のコンカレント操作で十分です。CPU集約型タスクにはプロセッサコア数を使用します。
OperationQueueとDispatchQueueの選択はタスクの複雑さに依存します。DispatchQueueはシンプルな非同期呼び出しのための軽量ツールです。OperationQueueは相互に関連する多くのタスクがある複雑なシナリオのためのより重いソリューションです。AppleはDispatchQueueから始め、依存関係やキャンセルが必要な場合にのみOperationQueueに切り替えることを推奨しています。ほとんどのiOSプロジェクトでは、両方のツールを組み合わせることで、パフォーマンスと柔軟性の最適なバランスが得られます。
Ray Wenderlich(2025)によると、大規模なiOSプロジェクトでは、OperationQueueは進捗とキャンセルを伴うコンテンツ読み込みに使用され、DispatchQueueは他のすべての非同期操作に使用されます。比率は約20対80でDispatchQueueが優勢です。
3つの例を見てみましょう:単純なBlockOperation、依存関係を持つカスタムOperation、データ読み込みのためのキャンセル可能な操作。
最も単純なケース — OperationQueueでブロックを実行し、completionBlockを通じて結果を処理します。すべてのOperationには組み込みのcompletionBlockプロパティがあり、main()の完了後に呼び出されます。
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
let data = NetworkService.fetchData()
OperationQueue.main.addOperation {
self.updateUI(data)
}
}
queue.addOperation(operation)
依存関係により、parseOperationはdownloadOperationの完了後にのみ開始されます。これによりネストされたコールバックの必要性がなくなります。
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)
let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)
定期的なisCancelledチェックでmain()をオーバーライドします。これにより、コストのかかる操作の完了を待つことなく、キャンセル時に操作を即座に停止できます。
class ImageLoadOperation: Operation {
override func main() {
guard !self.isCancelled else { return }
let image = self.downloadImage()
guard !self.isCancelled else { return }
OperationQueue.main.addOperation { self.display(image) }
}
}
操作のキャンセルはisCancelledフラグをtrueに設定しますが、既に実行中のmain()メソッドは停止しません。main()内のコードは自分でisCancelledをチェックし、必要に応じて終了する必要があります。これはAppleの設計上の決定であり、開発者がキャンセル時にリソースを適切に解放できるようにします。
isFinishedおよびisExecutingプロパティのKVO監視により、明示的なコールバックなしで操作の完了に反応できます。OperationQueueは完了した操作を自動的にキューから削除しますが、強参照が存在する限りメモリに残ります。KVOは、OperationQueueをRxSwiftやCombineなどのリアクティブフレームワークと統合するための基盤です。
KVOを通じてisCancelledを購読すると、操作キャンセル時にUIを更新できます(例:キャンセルされたダウンロードの代わりにプレースホルダーを表示)。isCancelledプロパティはKVO互換であり、リアクティブパイプラインに便利です。
大量の操作を作成しないでください — 各Operationはメモリ内の個別のオブジェクトです。タスクが短く依存関係を必要としない場合は、直接DispatchQueueを使用してください。OperationQueueは、明示的な依存関係、キャンセル、進捗監視を伴う複雑なシナリオに適しています。
コストのかかる操作の前にisCancelledをチェックしてください main()メソッド内で。ファイルのダウンロードや画像処理の場合、各重要なステップの後にチェックすることで、キャンセルへの迅速な応答が保証されます。main()の先頭と各主要操作の後にif isCancelled { return }を使用してください。
completionBlockを適切に管理してください。操作のcompletionBlockプロパティは、操作がキャンセルされた場合でもmain()の完了後に呼び出されます。誤ったデータでUIを更新しないように、completionBlock内でisCancelledをチェックしてください。OperationQueue.mainはDispatchQueue.mainと同様に、UI操作用のスレッドセーフなキューです。
循環依存関係を避けてください — サイクル内の操作はどれも開始されなくなります。OperationQueueは循環を自動的に検出しません:AがBに依存し、BがAに依存する場合、両方は永遠にready状態のままです。事前に依存関係グラフを計画してください。
よくある質問
OperationQueueはGCD上に構築され、依存関係、優先順位、KVO、操作のキャンセルを追加します。DispatchQueueはこれらの機能なしで単純な非同期タスクのための軽量ツールです。
maxConcurrentOperationCountプロパティを1に設定します。これにより、OperationQueueはすべての利点(依存関係、優先順位、キャンセル)を保持したまま順次キューになります。
cancel()メソッドはisCancelledフラグを設定しますが、実行中のmain()メソッドは停止しません。操作コードは自分でisCancelledをチェックして終了する必要があります。キャンセルは保留中および準備完了の操作に対してのみ機能します。
状態管理、非同期性、またはロジックの再利用が必要な場合は、Operationをサブクラス化する必要があります。BlockOperationは継承なしで単純な1回限りのタスクに適しています。
いいえ、メインスレッドでパラメータtrueを指定してwaitUntilFinishedを呼び出さない限りブロックしません。操作はデフォルトでバックグラウンドスレッドで実行され、結果はOperationQueue.mainを通じて返されます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。