2015-06-23 18 views
2

我一直在试图解决NSOperation子类中的一个问题,我觉得它可能与我们的KVO的手动更改通知有关。所有我检查的来源似乎做更新的NSOperation状态时的情况如下:多个KVO键:为什么要调用willChangeValueForKey:在didChangeValueForKey之前两次:?

[self willChangeValueForKey:@"isExecuting"]; 
[self willChangeValueForKey:@"isFinished"]; 
_isExecuting = NO; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 
[self didChangeValueForKey:@"isExecuting"]; 

相反,我们一直在做这样的:

[self willChangeValueForKey:@"isExecuting"]; 
_isExecuting = NO; 
[self didChangeValueForKey:@"isExecuting"]; 

[self willChangeValueForKey:@"isFinished"]; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 

任何人能告诉我,为什么前似乎是这样做的推荐方式?

似乎苹果的KVO文档也推荐了第一种方法。 (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html#//apple_ref/doc/uid/20002178-SW3)/

回答

0

原因是,从概念上讲,操作会将两个状态一起改变,只有在内部状态已经更新两个属性后才会通知观察者,因此,处理通知时,观察者看到一致的状态

如果你这样做:

[self willChangeValueForKey:@"isExecuting"]; 
_isExecuting = NO; 
[self didChangeValueForKey:@"isExecuting"]; 

那么观察员将得到该isExecuting性质改变通知didChange...通话过程中如果您在操作性质的。处理程序,他们合作(isExecuting返回NO)但还没有完成(isFinished仍然返回NO)。这没有意义。观察员可以做一些奇怪的事情。

+0

有趣。似乎这种模式需要了解NSOperation内部观察者如何处理状态变化。你知道有没有关于这方面的进一步文件? – fyell

+0

您是指操作队列如何观察其操作?这不一定就是这个。其他东西可以观察操作属性。我正在写关于一般情况。不,我没有关于队列如何观察他们的操作并对这些变化作出响应的进一步文档。 –

+0

不在NSOperationQueue级别。我假设当一个NSOperation被初始化时,它也会自己建立KVO。我做了这个假设,因为这个调用我在堆栈跟踪崩溃中看到'[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]'。 – fyell

0

我实现的NSOperation不按模式

[self willChangeValueForKey:@"isExecuting"]; 
[self willChangeValueForKey:@"isFinished"]; 
_isExecuting = NO; 
_isFinished = YES; 
[self didChangeValueForKey:@"isFinished"]; 
[self didChangeValueForKey:@"isExecuting"]; 

,而不是通过简单地做

self.executing = NO; 
self.finished = YES; 

..没有问题使用NSOperationQueues时(永无止境的操作等)。看来NSOperationQueue只会侦听'IsFinished'来确定NSOperation是否真正完成。这个其他答案更好地解释。

NSOperation KVO isFinished

相关问题