ネットワークタスクまたは操作の完了ブロックのメインスレッドで何かを実行する必要がある場合、それを取得するこれらの方法のどれが最も適切で、なぜですか?:
OperationQueue.main.addOperation
DispatchQueue.main.async
2種類のキューの違いの詳細については、Lionの回答を参照してください。
両方のアプローチが機能します。ただし、NSOperation
は、より高度なスケジューリング(依存関係、キャンセルなどを含む)が必要な場合に主に必要です。この場合、シンプルな
DispatchQueue.main.async { /* do work */ }
大丈夫です。それは同等です
dispatch_async(dispatch_get_main_queue(), ^{ /* do work */ });
objective-Cで、これもその言語で行う方法です。
NSOperationを使用する場合
NSOperation
APIは、明確に定義された機能ブロックをカプセル化するのに最適です。たとえば、NSOperation
サブクラスを使用して、アプリケーションのログインシーケンスをカプセル化できます。
依存関係管理はケーキの上のアイシングです。操作には、他の操作への依存関係があります。これは、Grand Central Dispatchにはない強力な機能です。特定の順序でいくつかのタスクを実行する必要がある場合は、操作が適切なソリューションです。
短期間で多数のオペレーションを作成している場合は、オペレーションでオーバーボードできます。これは、NSOperation API
に固有のオーバーヘッドにより、パフォーマンスの問題につながる可能性があります。
Grand Central Dispatchを使用する場合
Grand Central Dispatch
は、コードのブロックをシリアルキューまたは同時キューにディスパッチする必要がある場合に最適です。
簡単なタスクのためにNSOperation subclass
を作成する手間をかけたくない場合は、Grand Central Dispatch
が優れた代替手段です。 Grand Central Dispatch
のもう1つの利点は、関連するコードをまとめて保持できることです。次の例を見てください。
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Process Response
...
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// Update User Interface
...
})
})
データタスクの完了ハンドラーで、応答を処理し、メインキューにクロージャー(またはブロック)をディスパッチすることでユーザーインターフェイスを更新します。完了ハンドラーが実行されるスレッドがわからないため、これが必要です。これはほとんどの場合バックグラウンドスレッドです。
this source から逐語的に引用
DispatchQueueは、作業項目の実行を管理します。キューに送信された各作業項目は、システムが管理するスレッドのプールで処理されます。
参照: Apple Doc
NSOperationQueueクラスは、Operationオブジェクトのセットの実行を規制します。キューに追加された操作は、明示的にキャンセルされるか、タスクの実行が完了するまで、そのキューに残ります。キュー内の(ただしまだ実行されていない)操作自体は、優先度レベルと操作間オブジェクトの依存関係に従って編成され、それに応じて実行されます。アプリケーションは、複数の操作キューを作成し、それらのいずれかに操作を送信できます。
参照: Apple Doc
したがって、ネットワークコールの完了ブロックからメインスレッドで何かを実行する場合は、DispatchQueue.main.async
を優先する必要があります。特にUI Updates
に関連する場合!タスクが複雑な場合、実行中のタスクでさらに操作が必要な場合は、OperationQueue.main.addOperation
を使用できます。そうでない場合、DispatchQueue.main.async
は比較的最適なパフォーマンスを提供します。