2012-07-31 25 views
6

私は非常に非同期設計のiOSアプリケーションを開発中です。単一の概念的な「操作」が非同期的に実行され、応答(リモートサーバーへの呼び出し)を非同期的に受け取る多くの子ブロックをキューに入れる場合があります。これらの子ブロックのいずれかがエラー状態で実行を終了する可能性があります。子ブロックでエラーが発生した場合は、他の子ブロックを取り消す必要があります。エラー状態を親に渡し、親のエラー処理ブロックを実行する必要があります。非同期ブロックの推奨デザインパターン?

このような環境での作業に推奨されるデザインパターンやヒントは何ですか?

私はGCDのdispatch_group_asyncとdispatch_group_waitの機能について知っています。このアプリのデザインには欠陥があるかもしれませんが、ディスパッチ_グループ_アシンクで幸運を祈ることはできません。なぜなら、そのグループは子ブロックに「粘着性」ではないように見えるからです。

ありがとうございます!

答えて

5

おそらくあなたを助けるWWDCビデオ(2012)があります。これはカスタムNSOperationQueueを使用し、非同期ブロックをNSOperationsの内部に配置するので、ブロックにハンドルを保持し、残りのキューに入っているブロックを取り消すことができます。

考え方は、子ブロックのエラー処理で、NSOperationQueueを処理するクラスのメインスレッドでメソッドを呼び出すことです。クラスは残りの部分を適切にキャンセルすることができます。この方法では、子ブロックは自分のスレッドとメインスレッドについて知る必要があります。ここでは、ビデオ

https://developer.apple.com/videos/wwdc/2012/

へのリンクは、ビデオが「iOSの同時ユーザーインターフェイスの構築」と呼ばれています。関連する部分は主に後半にありますが、状況に応じて全体を見たいと思うでしょう。

EDIT:

可能な場合は、私が..私はあなたが後にしている思いものですうまくそれを一緒にラップした包埋ブロック、中に応答を扱うお勧めします

//Define an NSBlockOperation, and get weak reference to it 
NSBlockOperation *blockOp = [[NSBlockOperation alloc]init]; 
__weak NSBlockOperation *weakBlockOp = blockOp; 

//Define the block and add to the NSOperationQueue, when the view controller is popped 
//we can call -[NSOperationQueue cancelAllOperations] which will cancel all pending threaded ops 
[blockOp addExecutionBlock: ^{ 

    //Once a block is executing, will need to put manual checks to see if cancel flag has been set otherwise 
    //the operation will not be cancelled. The check is rather pointless in this example, but if the 
    //block contained multiple lines of long running code it would make sense to do this at safe points 
    if (![weakBlockOp isCancelled]) { 

     //substitute code in here, possibly use *synchronous* NSURLConnection to get 
     //what you need. This code will block the thread until the server response 
     //completes. Hence not executing the following block and keeping it on the 
     //queue. 
     __block NSData *temp; 
     response = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]]; 

     [operationQueue addOperationWithBlock:^{ 
      if (error) { 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         //Call selector on main thread to handle canceling 
         //Main thread can then use handle on NSOperationQueue 
         //to cancel the rest of the blocks 
        }); 
      else { 
       //Continue executing relevant code....  
      } 
     }]; 
    } 
}]; 
[operationQueue addOperation:blockOp]; 
+1

ありがとう、私はビデオを見ました。私が抱えているのは、非同期応答を待っている間に操作が本質的に待ち行列に保持される方法です。 NSOperationQueueを活用することができれば便利です。私は他のアプリでこのクラスを使用していましたが、以前は、レスポンス処理ではなく、アウトバウンドリクエストをキューで処理していました。このアプリケーションでは、応答が処理され、関連する子要求も完了するまで、操作は実行されません。 – xyzzycoder

+0

組み込みブロックに応答処理コードを入れることができますか?私の答えを更新します –

+0

あなたが 'dispatch_async(dispatch_get_main_queue()、^ {});ではなく' NSOperation'の世界にいるなら、なぜ[[NSOperationQueue mainQueue] addOperationWithBlock:^ {}]; ' ?あなたが持っているものは問題ありませんが、GCDコールとNSOperationQueueコールを混在させるのは奇妙です。 – Rob

-1

ココアで非同期動作を実現する方法はたくさんあります。

GCD、NSOperationQueue、performSelectorAfterDelay、独自のスレッドを作成する。これらのメカニズムを使用する適切な時期があります。ここで議論するには時間がかかりますが、記事で言及したことはアドレッシングが必要です。

子ブロックにエラーが発生した場合は、他の子ブロックを取り消す必要があります。エラー状態を親に通知し、親のエラー処理ブロックを実行する必要があります。

ブロックは、スタックの上にエラーをスローします。期間。

+0

ありがとうございます。このアプリケーションでは、サーバーとの通信チャネルが1つあり、クライアント/サーバー操作は暗黙的にシリアル化されています。スタックの上にエラーを渡すつもりはありません。 – xyzzycoder

+0

それでは、非同期呼び出しが必要です - GCDを使用するか、独自のスレッドを作成してください。 –