0

優れたAFNetworkingライブラリを使用していますが、NSOperationQueue で操作を追跡するのに問題があります。NSOperationQueue に NSOperation オブジェクトを追加していますが、進行状況を追跡する必要があります。そのため、UIProgressView を更新してキューが完了するまでの距離を表示し、キューが完了したらコード ブロックを実行します。

私はKVOを試しました-ここで答えを使用して: NSOperationQueueがすべてのタスクを終了したときに通知を受け取りますが、キュー内の操作が一時的に operationCount プロパティをデクリメントするのに十分な速さで完了する場合があるという問題に遭遇します(そこの2番目の答えで詳しく説明されています) 0 - これにより、受け入れられた回答のコードに問題が発生します。つまり、キュー内のすべてのオブジェクトが終了した後に実行されるコードが時期尚早に実行され、結果として進行状況の追跡が正確ではなくなります。

私が試したバリエーションは、NSOperationQueue に追加する各 NSOperation の成功ブロックで operationCount == 0 をチェックし、それに基づいてコードを実行することです。

    [AFImageRequestOperation *imgRequest = [AFImageRequestOperation imageRequestOperationWithRequest:urlRequest success:^(UIImage *image) {

     //Process image & save

            if(operationQ.operationCount == 0){
              // execute completion of Queue code here
            }
            else {
              // track progress of the queue here and update UIProgressView
            }
    }];

ただし、KVO と同じ問題が発生します。

完了ブロックを使用してディスパッチキューでGCDを使用することを考えました-NSOperationQueueを非同期にディスパッチしてから完了ブロックを実行しますが、キューの進行状況を追跡してUIProgressViewを更新することに関する問題は解決しません。

こちらも未使用

AFHttpClient enqueueBatchOfHTTPRequestOperations:(NSArray *) progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations)progressBlock completionBlock:^(NSArray *operations)completionBlock

私の画像は(1つのベースURLではなく)いくつかの異なるURLから来ているためです。

提案や指針をいただければ幸いです。ありがとう。

ただ最後の更新:

マットの助けを借りて(受け入れられた回答を参照)、最後に AFHTTPClient enqueueBatchOfHTTPRequestOperations を使用してこの問題を解決し、コメントにも注意してください。

AFHTTPClient を使用せず、NSOperationQueue だけを使用する別のソリューションに出くわしました。誰にとっても役立つ場合に備えて、これも含めましたが、AFNetworking ライブラリを使用している場合は、受け入れられた回答をお勧めします (最もエレガントで実装が簡単であるため)。

4

2 に答える 2

2

AFHTTPClient ではなく NSOperationQueue のみを使用している場合の別の (洗練されていない) ソリューションは次のとおりです (次のコードがループ内にあり、複数の要求を作成して NSOperationQueue に追加すると仮定します)。

       [AFImageRequestOperation *imgRequest = [AFImageRequestOperation imageRequestOperationWithRequest:urlRequest success:^(UIImage *image) {

     //Process image & save

      operationNum++ 
      //initially operationNum set to zero, so this will now increment to 1 on first run of the loop

      if(operationNum == totalNumOperations){ 
         //totalNumOperations would be set to the total number of operations you intend to add to the queue (pre-determined e.g. by [array count] property which would also be how many times the loop will run)

         // code to execute when queue is finished here
       }
       else {
          // track progress of the queue here and update UIProgressView

          float progress = (float)operationNum / totalNumOperations
          [progView setProgress:progress] //set the UIProgressView.progress property
        }
     }];

これらの NSOperation オブジェクトを NSOperationQueue に追加すると、各 NSOperation オブジェクトの成功ブロックに埋め込まれたキュー完了コードを実行する前に、各操作の成功ブロックが確実に完了します。注: NSOperationQueue.operationCount プロパティは、キューを終了する操作と次の操作が追加される直前に operationCount がゼロである状態が存在する可能性があるため、高速操作では信頼できないため使用されません。代わりに operationCount = 0 の場合、キューの完了コードが途中で実行されます。

于 2013-05-23T16:41:25.837 に答える