6

非同期性の高いデザインのiOSアプリに取り組んでいます。単一の概念的な「操作」が、非同期で実行され、それらの応答(リモートサーバーへの呼び出し)を非同期で受信する多くの子ブロックをキューに入れる場合があります。これらの子ブロックのいずれかがエラー状態で実行を終了する可能性があります。いずれかの子ブロックでエラーが発生した場合は、他の子ブロックをキャンセルし、エラー状態を親まで浸透させ、親のエラー処理ブロックを実行する必要があります。

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

GCDのdispatch_group_asyncおよびdispatch_group_wait機能を認識しています。このアプリの設計に欠陥がある可能性がありますが、グループが子ブロックに「固定」されていないように見えるため、dispatch_group_asyncを使用することはできませんでした。

前もって感謝します!

4

3 に答える 3

5

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

子ブロックのエラー処理を使用して、を処理するクラスのメインスレッドでメソッドを呼び出すことをお勧めしますNSOperationQueue。その後、クラスは残りを適切にキャンセルできます。このように、子ブロックは自分のスレッドとメインスレッドについてのみ知る必要があります。ここにビデオへのリンクがあります

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

このビデオは「iOSでの同時ユーザーインターフェイスの構築」と呼ばれています。関連する部分は主に後半にありますが、それが文脈にうまく収まっているので、おそらく全体を見たいと思うでしょう。

編集:

可能であれば、埋め込みブロックで応答を処理することをお勧めします。これにより、応答がうまくまとめられます。これが、あなたが求めているものだと思います。

//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];
于 2012-07-31T19:34:43.933 に答える
1

この質問を投稿してから私が遭遇したパターンの1つは、セマフォを使用して、非同期操作を同期操作に変更することでした。これはかなり便利です。このブログ投稿では、概念について詳しく説明しています。

http://www.g8production.com/post/76942348764/wait-for-blocks-execution-using-a-dispatch-semaphore

于 2014-09-20T23:31:02.640 に答える
-1

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

GCD、NSOperationQueue、performSelectorAfterDelay、独自のスレッドを作成します。これらのメカニズムを使用する適切な時期があります。ここで議論するには長すぎますが、投稿で言及したことには対処する必要があります。

いずれかの子ブロックでエラーが発生した場合は、他の子ブロックをキャンセルし、エラー状態を親まで浸透させ、親のエラー処理ブロックを実行する必要があります。

ブロックはスタックにエラーをスローできません。限目。

于 2012-08-08T03:17:37.160 に答える