Cocoa KVO:observeValueForKeyPath:ofObject:change:context:为一次值更改调用两次

Car*_*loS 2 iphone cocoa objective-c key-value-observing

我有一个NSOperation子类,它实现了setFinished:生成KVO通知:

-(void)setFinished:(BOOL)isFinished
{
    LogError(@"%@ will will changing isFinished to %d",self,isFinished);
    [self willChangeValueForKey:@"isFinished"];
    LogError(@"%@ did will changing isFinished to %d",self,isFinished);
    _isFinished = isFinished;
    LogError(@"%@ will did changing isFinished to %d",self,isFinished);
    [self didChangeValueForKey:@"isFinished"];
    LogError(@"%@ did did changing isFinished to %d",self,isFinished);
}
Run Code Online (Sandbox Code Playgroud)

我也确定我只将观察者添加到操作一次.

奇怪的事情来了,有时候observeValueForKeyPath:ofObject:change:context:这个对象的isFinished密钥路径被调用两次,指的是日志,我只发现setFinished:一次调用,而且addObserver:forKeyPath:这个操作只被调用一次.

另外,我发现它的序列是这样的:

will will changing isFinished to 1
did will changing isFinished to 1
will did changing isFinished to 1
calling observeValueForKeyPath for object
did did changing isFinished to 1
calling observeValueForKeyPath for object
Run Code Online (Sandbox Code Playgroud)

所以任何人都有任何线索吗?

rob*_*off 5

如果你想利用调用的责任willChangeValueForKey:didChangeValueForKey:,你要告诉系统.你可以用两种方式做到这一点:

  • 您可以+automaticallyNotifiesObserversForKey:在类上覆盖(类方法)以NO在键出现时返回finished.这在"键值观察编程指南"的"手动更改通知"中记录.

  • 你可以实现+automaticallyNotifiesObserversOfFinished返回NO.这在NSKeyValueObserving.h头文件中的注释中记录+automaticallyNotifiesObserversForKey:.

如果未正确实现这些类方法之一,系统将在setFinished:返回时自动通知观察者.它看起来就像你在日志中看到的那样.