不了解NSOperationQueue序列

时间:2014-09-26 16:47:21

标签: ios objective-c nsoperation nsoperationqueue nsblockoperation

我有一个名为DataFetcher的模型类,它通过Web服务获取数据,然后将数据保存到Core Data数据存储区,然后通过委托方法更新ViewController。这是正常的序列(它正常工作)而不使用NSOperation:

NSArray *serviceQueryResult = [self queryServiceFor:@"car"];
[self setData:serviceQueryResult];
[self persistData:_data];
[_loadDelegate updateCount:_data.count]; 
[_loadDelegate receivedData:_data];

我需要在后台线程上放置Web服务调用和数据库更新调用。我的想法是创建一个NSBlockOperation来进行Web服务调用,然后另一个NSBlockOperation来进行数据库更新。在数据库更新操作开始之前,Web服务操作将完成依赖关系。这是我试图实现的代码:

__weak DataFetcher *weakSelf = self;
__block NSArray *serviceQUeryResult;
NSBlockOperation *webServiceOperation = [NSBlockOperation blockOperationWithBlock:^{
    serviceQUeryResult = [weakSelf queryServiceFor:@"mini"];
    [weakSelf setData:serviceQUeryResult];
}];
NSBlockOperation *dbInsertOperation = [NSBlockOperation blockOperationWithBlock:^{
    [weakSelf persistData:serviceQUeryResult];
}];

[webServiceOperation addDependency:dbInsertOperation];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:webServiceOperation];

以这种方式设置时,我的queryServiceFor:方法永远不会被调用。我也不确定两个委托方法调用的位置,因为它们更新了UI并且应该在主线程上。我过去曾多次使用过GCD,但现在需要一些NSOperations的额外功能。有人可以帮忙吗?谢谢!

1 个答案:

答案 0 :(得分:2)

根本问题是您已声明webServiceOperation依赖于dbInsertOperation(即在webServiceOperation完成之前它不会开始dbInsertOperation ,但是你永远不会开始dbInsertOperation,所以webServiceOperation将永远无法运行。

  1. 如果您想dbInsertOperation依赖于webServiceOperation,您可能不想要:

    [webServiceOperation addDependency:dbInsertOperation];
    

    你想要:

    [dbInsertOperation addDependency:webServiceOperation];
    
  2. 创建此依赖关系后,请务必将这些操作的两个添加到您的队列中。

    [queue addOperation:webServiceOperation];
    [queue addOperation:dbInsertOperation];
    

    依赖关系将确保dbInsertOperationwebServiceOperation完成之前不会开始。注意,这假设webServiceOperation同步执行其块。如果网络请求以异步方式运行,您可能希望将其包装在自己的并发/异步NSOperation子类中。


  3. 如果您想从这些后台操作更新UI,您可以:

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // update the UI here
    }];
    

    或使用GCD,如果您愿意:

    dispatch_async(dispatch_get_main_queue(), ^{
        // update the UI here
    });