0

我正在使用AFNetworking库,它非常好,但是我无法跟踪 NSOperationQueue 中的操作。我正在将 NSOperation 对象添加到 NSOperationQueue,并且我需要跟踪进度 - 因此更新 UIProgressView 以显示队列完成的距离,然后在队列完成后执行一段代码。

我已经尝试过 KVO - 在这里使用答案:当 NSOperationQueue 完成所有任务时获取通知但是我遇到了问题(详细说明了那里的第二个答案),有时队列中的操作可能完成得足够快,可以暂时减少 operationCount 属性到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

因为我的图像来自几个不同的 URL(而不是一个基本 URL)。

任何建议或指示将不胜感激。谢谢。

只是最后的更新:

最后在 Matt 的帮助下使用 AFHTTPClient enqueueBatchOfHTTPRequestOperations 解决了这个问题(请参阅接受的答案),并注意注释。

我确实遇到了另一个不使用 AFHTTPClient 而是单独使用 NSOperationQueue 的解决方案。我也将其包括在内,以防它对任何人都有用,但如果您使用的是 AFNetworking 库,我会推荐接受的答案(因为它最优雅且易于实现)。

4

2 回答 2

4

AFHTTPClient -enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:是正确的方法。该方法采用一系列请求操作,可以从任意请求构建,而不仅仅是共享域的请求。

于 2013-05-22T16:46:49.820 回答
2

如果您只使用 NSOperationQueue 而不是 AFHTTPClient,则另一个(不那么优雅)的解决方案如下(假设以下代码将在某个循环中创建多个请求并添加到 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 为零,所以如果我们比较 NSOperationQueue。 operationCount = 0 而不是队列的完成代码会过早执行。

于 2013-05-23T16:41:25.837 回答