とにかくメインスレッドをブロックしない非同期 NSURLConnection を使用しているのに、AFHTTPClient が操作を使用するのはなぜですか?
これは実際には優れた質問です。
実際、実行可能な「HTTPRequestOperation」クラスは、すべてからサブクラス化する必要はありませんNSOperation
。のデザインはAFHTTPRequestOperation
、アップルのエンジニアである「Quinn」によって導入された「オリジナル」のデザインに基づいている可能性が非常に高く、彼はクラスで最初の「参照デザイン」を発明しQHTTPOperation
、多くの貴重なサンプルも提供しました。見てみましょう。この最初の設計は、a をサブクラスNSOperation
化し、オブジェクトをカプセル化しNSURLConnection
ます。
この設計には多くの利点があります。
のサブクラスであるNSOperation
ため、ネットワーク リクエストは「非同期操作」のように見えます。つまり、基本的に、ネットワーク要求には主要なメソッドがstart
ありcancel
、要求の最終的な結果を知らせる完了ハンドラーがあります。この汎用API は、非同期ネットワーク操作にとって重要であるため、より一般的な非同期操作になります。
クラスであるため、リクエストに関連するすべての状態変数をカプセル化します。たとえば、リクエスト、レスポンス、レスポンス データ、エラー (存在する場合)、さらにいくつかの関連する状態変数などです。1 つのデリゲート オブジェクトのデリゲート メソッドで複数のリクエストを処理する必要がある場合に難しくなり始めるデリゲート アプローチとは異なり、「ネットワーク リクエスト オブジェクト」は非常に使いやすくなります。
NSOperation
オブジェクトは にキューに入れることができますNSOperationQueue
。これにより、リクエストの順序、具体的にはその他の操作、および多数の場合は同時にアクティブな操作 (リクエスト) の数を定義できます。
NSOperation
他の操作の間で多かれ少なかれ複雑な依存関係を定義できます。これにより、「ビジネスロジック」のレイヤーを追加できます。時折、これはより複雑な非同期問題を解決するのに非常に便利になります。
したがって、すでに非同期の が のサブクラスにカプセル化された理由は、前述の利点です。その理由は、同期関数のように にラップして、で実行できるようにすることではありませんでした。NSURLConnection
NSOperation
NSOperation
NSOperationQueue
実は、これには大きな誤解があります。多くの人は、ネットワーク要求操作のメソッドが の実行コンテキストで実行されると考えているようですNSOperation
(たとえば、NSOperationQueue に追加された場合)。ただし、これは当てはまりません (他のさまざまな実装では小さな例外が発生する可能性があります)。メソッド (主に のデリゲート メソッドNSULRConnection
)の実行コンテキストは、サブクラスによって作成される専用のプライベート スレッドです。NSOperation
基礎となる下位レベルの関数NSURLConnection
も、プライベート実行コンテキスト (1 つまたは複数のスレッド) で実行されます。
メソッドのみがstart
操作の実行コンテキストで実行され、すぐに返されます。つまり、操作がディスパッチされたキュー (ディスパッチ キューまたは NSOperationQueue など) がある場合、start
メソッドのみがキューの実行コンテキストで実行されます。
ただし、の状態は、ネットワーク リクエストが実際に終了するまで延期されますNSOperation
。この状態は、他のオブジェクトとisFinished
にとって重要な意味を持ちます。この状態は、このリクエストが終了したことをキューやその他の操作に通知します。NSOperation
NSOperationQueue
したがって、NSOperation
はネットワーク リクエストの機能の実行コンテキストを定義するための手段ではなく、他の操作との関係を整理してセットアップするための手段です。
解析する必要があるデータを取得したら、データを解析する新しい操作を作成する必要がありますか? 操作でもデータを解析してから、解析されたオブジェクトを返す方が良いと思いますか?
まあ、あなたはそれを行うことができます。ただし、これは良い設計上の決定とは言えません。操作は特定のタスクのみを処理する必要があります。ネットワーク操作はその 1 つであり、解析タスク _ は別のタスクであり、これも操作になる可能性があります。
この理由の 1 つは、操作が主に必要とするシステム リソース (CPU、メモリ、IO など) に関して操作を「分類」できることです。異なる「タスク タイプ」をマージすると、それらを専用キューに関連付けて制御することができなくなります。システム リソースの使用率 (以下を参照)。
もちろん、解析タスクを操作にすることもできます。ただし、これが理にかなっているかどうかは次のとおりです。
特定のタスク (または機能) を作成するかどうかの決定NSOperation
は、次の考慮事項によって異なります。
そのタスクが完了するまでに (ユーザーの観点から) 長い時間がかかる可能性があるため、(開発者として) ユーザーにタスクをキャンセルする機会を与えたい場合、「操作」は正当化されます: (覚えておいてください: 非同期操作には主な方法cancel
)
もう 1 つの理由は、CPU、メモリ、IO などの特定の共有および制限されたシステム リソースに関連付けられている特定の実行コンテキストに操作を関連付けることです。システム リソース。たとえば、「ディスクにバインドされた」タスクがあるとします。この場合、NSOperationQueue
同時操作の数は 1 で、特定の「役割」と適切な名前 (「DiskBoundQueue」など) を与えます。キューは、操作の作成と開始を制御するのに役立ち、制限されたシステム リソースが使い果たされないように、並列実行操作の数を強制的に制限します。次に、「ディスクにバインドされた」操作を専用の「DiskBoundQueue」にのみ追加します。ディスクは、異なるタスクから同時にアクセスされると最適に動作しないため、同時操作の数は 1 に設定されます。つまり、このような専用キューは、システム リソースの使用率を最適化するのに役立ちます。
操作間に依存関係がある場合、操作 A と操作 B が正常に終了した場合にのみ操作 C を開始するとします。NSOperation
そのような依存関係を確立する手段を提供します。
さらに別の理由として、共有リソースへの同時アクセスを制御することも考えられます。特定の共有リソース (ivar など) にアクセスする複数の操作が serial に追加されたNSOperationQueue
場合、共有リソースへのアクセスはシリアル化されるため、「スレッドセーフ」になります。 "。ただし、同時実行性が唯一の要件である場合は、ディスパッチ キューとブロックを利用したより単純なアプローチを使用することをお勧めします。
それで、あなたの質問に関してより正確にするために:いいえ、NSOperation
特大になる可能性があります. 専用のディスパッチ キューを使用する方がよい場合があります。これは、共有リソースの同時アクセスも解決するシリアル キューである可能性があります。
同じ件名で、NSData を取得して NSDictionary に解析するカスタム汎用 XMLParser クラスがあり、すべての応答にそれを使用したいと考えています。応答が既に解析された?
AFHTTPRequestOperation
実行可能なアプローチは、たとえば、または AFClient の完了ハンドラー内で XML パーサーを開始するだけです。
XML パーサーの結果に依存する別の操作がある場合、1 つの方法は、XML パーサーを にカプセル化しNSOperation
、他の操作を XML パーサー操作に依存させることです。(ただし、そのような依存関係には他のより簡単なソリューションがあります)