我正在研究NSOperation子类,我遇到了这个非常奇怪的问题,连续两次调用完成块。 KVO调用似乎很好但是completionBlock仍然被奇怪地调用了两次。我误解了NSOperation吗?文档说明当isFinished
变为YES
并且只在我的代码中发生一次时调用完成块:
- (void)main {
@autoreleasepool {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isReady"];
executing = YES;
[self didChangeValueForKey:@"isReady"];
[self didChangeValueForKey:@"isExecuting"];
//start the operation
}
}
然后我就像这样设置completionBlock
:
self.completionBlock = ^{
NSLog(@"Completed");
}
当它完成时,这个方法被调用(它被称为ONCE,我再次检查它)
- (void)completeOperation {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
executing = NO;
completed = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
但是,completionBlock被调用两次并在控制台中两次打印“已完成”。
以下是指示当前状态的方法:
- (BOOL)isReady {
if (executing || cancelled || completed) {
return NO;
}
return YES;
}
- (BOOL)isCancelled {
return cancelled;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return completed;
}
isCancelled
永远不会在我的测试代码中转向YES
,因此无法将其作为原因。
我真的不明白为什么completeBlock被调用两次。即使从完成块内部将完成块设置为nil,有时也会被称为两次,这甚至更奇怪。
答案 0 :(得分:4)
不确定这是否是原因,但根据我的经验,不需要覆盖只读状态属性。你负责在主循环中定期检查isCancelled,如果它被设置为无法正常运行,但我相信其他状态标志(isReady,isFinished,isExecuting)会自动处理。
如果您取消状态标记处理并在-main
中执行您的流程,它会触发多少次?
编辑:假设您要覆盖这些标志以允许并发,那么您应该阅读注释in the docs
根据它的外观,您永远不需要覆盖isReady
或isCancelled
,而是根据文档中的说明覆盖-start
。