我在NSOperations
添加了一堆NSOperationQueue
。操作队列将maxConcurrentOperationCount
设置为1,以便NSOperations
一个接一个地运行。
现在,在completionBlock
的{{1}}中,我想通过NSOperation
上的NSOperations
取消所有待审cancelAllOperations
。
这样做是否安全?我是否可以确定只有在前一个操作的NSOperationQueue
完全执行后才调用下一个操作的start
- 方法?或者执行上一个操作的completionBlock
并同时运行当前操作的任务?
我之所以要问:我使用AFNetworking来执行一批completionBlock
,并且只有在批量的所有先前请求都成功时才想执行一个请求。
答案 0 :(得分:5)
我的发现似乎不再适用。我在iOS 8和iOS 9上重新运行测试,并且操作的完成块总是与下一个操作同时运行。目前,我没有看到让操作等待前一个完成块完成的方法。
我刚刚在一个示例项目中尝试了这个场景。结果如下:
如果NSOperationQueue
的{{1}}设置为1,则maxConcurrentOperationCount
的{{1}}和队列中的下一个NSOperation
会同时运行。
但是,如果通过调用completionBlock
将每个NSOperation
链接到其先前的操作,则操作的执行将一直等到上一个操作的NSOperation
完成。
因此,如果要取消当前操作的addDependency:
中的下一个操作并确保在启动之前取消它,则必须通过调用在completionBlock
之间设置依赖关系completionBlock
答案 1 :(得分:1)
NSOperation仅根据操作的完成状态建立依赖性,而不根据完成的操作结果建立依赖性。
但是,我遇到的大多数情况都是这样,操作的执行不仅取决于其他一些操作的完成,而且还取决于从完成的操作获得的结果。
我最终按照以下方法进行操作,但仍在探索是否有更好的方法:
1)操作A运行
2)Operation-A参与竞争,completionBlock运行
3)在OperationA的完成块中,检查从Operation-A获得的结果。
因此,这最终是一系列操作,这些操作将根据已完成操作的结果动态添加到队列中。
答案 2 :(得分:1)
我想出了另一种看似更好的方法,以确保仅在满足某些条件(基于先前完成的操作的结果)时才执行操作,否则操作将被取消。
这里的一个重要考虑因素是,不应在操作子类中编写用于运行操作的条件检查的代码,这样可以使操作子类在不同的场景和应用程序之间相互兼容。
解决方案: -在子类内部具有条件块属性,并设置实例化操作的任何条件形式。 -重写NSOperation子类的“ isReady” getter,检查那里的条件,从而确定其是否准备好执行。 -如果[super isReady]为YES,则意味着相关操作已全部完成,然后评估必要条件。 -如果通过了条件检查,则返回“是”。否则,将isCancelled设置为YES,然后为isReady返回YES
代码: 在接口文件中具有block属性:
typedef BOOL(^ConditionBlock)(void);
@property (copy) ConditionBlock conditionBlock;
在实现中,重写isReady并取消:
@implementation ConditionalOperation
- (BOOL)isReady {
if([super isReady]) {
if(self.conditionBlock) {
if(!self.conditionBlock()) {
[self setCancelled:YES];
}
return YES;
} else {
return YES;
}
} else {
return NO;
}
}