根据Apple的文档,NSOperationQueue / NSOperation使用GCD。它提供了取消等功能,这在GCD中是不可用的。问题:如果GCD没有这种机制(或是否有机制),NSOperation如何实施取消?
答案 0 :(得分:3)
根据NSOperationQueue Class Reference:
排队操作在开始执行之前被取消。如果操作已在执行,则由该操作识别取消并停止正在执行的操作。
取消操作不会立即强制它停止它 是在做。虽然尊重isCancelled返回的值是 期望所有操作,您的代码必须明确检查值 通过此方法返回并根据需要中止。默认 NSOperation的实施确实包括取消检查。 例如,如果在start方法之前取消操作 在调用时,start方法退出而不启动任务。
注意:在OS X v10.6中,取消方法的行为会有所不同 取决于操作当前是否在操作队列中。 对于未排队的操作,此方法将操作标记为已完成 立即生成适当的KVO通知。排队 操作,它只是将操作标记为准备执行并让 队列调用其start方法,随后退出并生成结果 从队列中清除操作。
您应始终支持任何自定义代码中的取消语义 你写。特别是,您的主要任务代码应该定期 检查isCancelled方法的值。如果方法永远返回 是的,您的操作对象应该清理并尽快退出 可能的。
据我了解,-[NSOperation cancel]
只标记了一个标记,可能是isCancel
。在-[NSOperation start]
的顶部,它会检查标志,然后退出,如果它是真的
默认情况下,Apple仅支持取消当前未执行的操作。如果它在执行时被取消,则责任在-[NSOperation main]
代码中,用户自己实现。
使用GCD,您可以通过将块包装在具有isCancel标志的类中来实现。在块的第一行,检查标志并退出,如果它是真的。
@interface CancelableBlock : NSObject
@property (copy) dispatch_block_t block;
@property (assign) BOOL isCancel;
- (dispatch_block_t)wrappedBlock;
@end
@implementation CancelableBlock
- (dispatch_block_t)wrappedBlock {
return ^{ if (self.isCancel) return; self.block(); };
}
@end
使用时
dispatch_async(queue, [myblock wrappedBlock]);
答案 1 :(得分:0)
近似答案:每个NSOperation存储一个被取消的位。当操作开始执行时,它会在执行任何操作之前检查已取消的位。