多个KVO密钥:为什么在didChangeValueForKey之前调用willChangeValueForKey:两次:?

时间:2015-06-23 00:01:47

标签: ios objective-c cocoa key-value-observing nsoperation

我一直试图解决我们的NSOperation子类中的问题,我觉得它可能与我们的KVO手动更改通知有关。在更新NSOperation状态时,我检查过的所有来源似乎都会执行以下操作:

[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"];

有人可以告诉我为什么前者似乎是推荐的做法吗?

Apple的KVO文档似乎也推荐了第一种方法。不幸的是,他们无法解释原因。(https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html#//apple_ref/doc/uid/20002178-SW3)/

2 个答案:

答案 0 :(得分:1)

原因在于,从概念上讲,操作正在将两种状态一起改变。您希望仅在为两个属性更新内部状态后才通知观察者,以便在处理通知时,观察者看到一致的状态。

如果你这样做:

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

然后观察者将在isExecuting调用期间获得didChange...属性的更改通知。如果他们检查其处理程序中的操作属性,他们可以看到操作没有执行(isExecuting返回NO)但还没有完成(isFinished仍然返回NO) 。这没有意义。观察者可以做一些奇怪的事情。

答案 1 :(得分: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