AFNetworking&处理NSOperationQueue - 在完成时执行代码并跟踪进度

时间:2013-05-22 14:14:17

标签: ios objective-c afnetworking

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

我已经尝试过KVO - 使用这里的答案:Get notification when NSOperationQueue finishes all tasks但是我遇到了问题(详细说明了那里的第二个答案),有时队列中的操作可能足够快地完成以暂时减少operationCount属性为0 - 然后导致接受的答案中的代码出现问题 - 即在队列中的所有对象完成后过早执行要执行的代码,因此进度跟踪将不准确。

我尝试过的一个变体是检查每个NSOperation的成功块中的operationCount == 0,我将其添加到NSOperationQueue然后根据它执行代码,例如

    [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

因为我的图片来自几个不同的网址(而不是一个基本网址)。

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

最后更新:

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

我确实遇到过另一种不使用AFHTTPClient的解决方案,而是单独使用NSOperationQueue。我已将其包括在内,以防任何人使用它,但如果您使用AFNetworking图书馆,我建议您接受的答案(因为它最常见)优雅且易于实施)。

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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,然后队列的完成代码将过早执行。