【问题标题】:NSOperation and NSOperationQueueNSOperation 和 NSOperationQueue
【发布时间】:2013-10-04 15:16:14
【问题描述】:

我正在同时从服务器下载一些信息,并且我正在使用 NSOperationQueue。我有一个问题。例如,如果下载操作由于某种原因失败,我不想从队列中删除该操作。

现在即使它失败了,一旦它从服务器得到响应,操作就会从队列中删除。

有没有办法告诉队列一个特定的操作在逻辑上没有完成,它应该把它留在队列中?

就我而言,我正在下载一组信息。例如,获取一个县的所有地方,然后获取每个县的所有房屋。因此,在某些情况下,如果用户未使用有效令牌登录,则无法下载县。在这种情况下,服务器返回失败消息。我想将这些项目保留在队列中,以便在用户登录应用时重试。

示例代码

self.downloadQueue.maxConcurrentOperationCount = 1;
    for(Campaign *campaign in campaigns)
    {
        isContentUpdated = false;
        if(self.operation)
            self.operation = Nil;
        self.operation = [[DownloadOutlets alloc] initWithCampaign:campaign];
        [self.downloadQueue addOperation:operation];
    }

其中 downloadQueue 是一个 NSOperationQueue 并且 DownloadOutlets 扩展了 NSOperation。 谢谢

【问题讨论】:

  • 您的操作设置如何?显示一些代码示例。
  • 什么意思?如果一个操作已经执行了所有代码(无论是成功还是失败),为什么还要在队列中保留一个操作?
  • 就我而言,我正在下载一组信息。例如,获取一个县的所有地方,然后获取每个县的所有房屋。因此,在某些情况下,如果用户未使用有效令牌登录,则无法下载县。在这种情况下,服务器返回失败消息。我想保留这些项目在队列中。
  • 你可能不想让他们在队列中;将失败的那些移到“pendingToken”队列(数组)并在令牌故障得到解决后重新入队。

标签: ios objective-c nsoperation nsoperationqueue


【解决方案1】:

您不应该将失败的操作保留在队列中。失败的操作已执行其任务。您应该让您的操作控制器通过completionBlock 或其他方式监听操作状态,并决定下一步该做什么。如果确定操作失败但应该重试类似的操作,则应添加另一个操作以再次执行任务。

另一种方法是在操作中重试下载,直到成功,然后才结束操作。然而,这不是最佳设计,因为操作没有也不应该拥有决定是否重试、通知用户等所需的所有信息。

【讨论】:

    【解决方案2】:

    您不应该将失败的操作保留在队列中,而是使用队列进行串行获取数据,如果操作失败则停止排队:

    @implementation DataAdapter
    // ...
    
    -(void)setup{
         // weak reference to self to avoid retain cycle
         __weak DataAdapter* selfRef= self;
    
         // create a block that will run inside the operation queue
         void(^pullCountriesBlock)(void)= ^{
               [[DownloadManager instance] fetchAllCountriesWithCompletionBlock:^(Result* result){
               if(result.successful){
                    // on success
                    [selfRef didFetchDataForAction:action];
               }else{
                    // on failure
                    [selfRef failedToFetchDataForAction:action];
               }
         };
    
         self.actions= [NSMutableArray new];
         [self.actions addObject:[DownloadAction actionWithBlock:pullCountriesBlock];
         // add other actions
         // ...
         [self fetchData];
    }
    
    }
    
    -(void)fetchData{
         if(self.currentActionIndex >= self.actions.count){
               [self finishedFetchingData]; 
               return;
         }
    
         [self fetchDataForAction: self.actions[self.currentActionIndex] ];
    }
    
    -(void)fetchDataForAction:(DownloadAction*)action
          [self.myOperationQueueImplementation enqueueOperationWithBlock:action.block];
    }
    

    如果下载成功,只需将下一个动作排入队列(增加 currentActionIndex 并调用fetchData)。如果失败,您可以采取相应措施。我要做的是在第一次调用 fetchData 之前开始监听有趣的 NSNotificationCenter 事件。您可以收听 UserDidLogInNotification 或任何其他可能允许队列继续运行下载的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多