如何取消NSOperation的依赖项?

时间:2015-01-21 14:32:47

标签: ios asynchronous nsoperation nsoperationqueue

我在依赖关系图中有一些NSOperation

NSOperation *op1 = ...;
NSOperation *op2 = ...;

[op2 addDependency:op1];

以下是我如何运行它们:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:op1];
[queue addOperation:op2];

现在我需要取消它们。如何确保取消依赖关系图中的所有NSOperation,并且不会取消其他NSOperation


我尝试了什么:

cancel上调用NSOperation并不会取消另一个(据我所知):

[op1 cancel]; // doesn't cancel op2
// -- or --
[op2 cancel]; // doesn't cancel op1

取消队列还会取消不属于op1op2的依赖关系图的操作(如果队列中有任何此类操作):

[queue cancelAllOperations];

所以我使用自定义方法解决了这个问题,该方法以递归方式查看NSOperation的依赖关系并取消它们。但是,我对这个解决方案不满意,因为我觉得我正在与框架作斗争:

- (void)recursiveCancel:(NSOperation *)op
{
    [op cancel];
    for (NSOperation *dep in op.dependencies)
    {
        [self recursiveCancel:op];
    }
}

2 个答案:

答案 0 :(得分:10)

不存在NSOperation自动取消其依赖关系的概念。这是因为多个NSOperation可能依赖于同一个NSOperation。依赖关系严格存在,以延迟特定NSOperation的执行,直到其所有依赖NSOperation完成。

您可以考虑编写NSOperation的子类:

@interface NSOperationOneToOne : NSOperation
- (void)addOneToOneDependency:(NSOperation *)operation;
- (void)removeOneToOneDependency:(NSOperation *)operation;
@end

@implementation NSOperationOneToOne {
  NSMutableArray *oneToOneDependencies;
}
- (void)addOneToOneDependency:(NSOperation *)operation {
  [oneToOneDependencies addObject:operation];
  [self addDependency:operation];
}
- (void)removeOneToOneDependency:(NSOperation *)operation {
  [oneToOneDependencies removeObject:operation];
  [self removeDependency:operation];
}
- (void)cancel {
  [super cancel];
  [oneToOneDependencies makeObjectsPerformSelector:@selector(cancel)];
}
@end

注意:上述代码不保证没有错误。

答案 1 :(得分:2)

听起来像是在尝试将操作组合在同一个队列中。为了实现这一目标,最好使用每组队列将它们拆分。因此,对于每个组,在并发模式下创建一个NSOperation子类,包括一个队列,将每个子操作添加到队列中。覆盖取消并调用[超级取消]然后调用[self.queue cancelAllOperations]。

这种方法的一个巨大优势是您可以通过再次添加到子队列来重试操作,而不会影响主队列的顺序。