1

我正在同时从服务器下载一些信息,并且我正在使用 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。谢谢

4

2 回答 2

1

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

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

于 2013-10-04T15:40:47.607 回答
0

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

@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 或任何其他可能允许队列继续运行下载的内容。

于 2013-10-04T21:18:17.740 回答