2

我有一个 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);
}

我也确信我只将观察者添加到操作中一次。

奇怪的事情来了,有时候observeValueForKeyPath:ofObject:change:context:对于这个对象的isFinishedkey path被调用了两次,参考日志,我发现只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

所以有人有任何线索吗?

4

2 回答 2

5

如果你想对调用willChangeValueForKey:and负责didChangeValueForKey:,你必须告诉系统。您可以通过两种方式做到这一点:

  • 您可以在您的类上覆盖+automaticallyNotifiesObserversForKey:(类方法)以NO在键为finished. 这记录在*Key-Value Observing Programming Guide 中的“手动更改通知”下。

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

如果你没有正确实现这些类方法之一,系统会在setFinished:返回时自动通知观察者。看起来这就是您在日志中看到的内容。

于 2013-06-24T03:32:33.887 回答
-1

你不需要实现'setFinished:'。

KVO 方法 observeValueForKeyPath:ofObject:change:context: 从 setFinished: 被调用一次,因为你已经明确地使用

[self willChangeValueForKey:@"isFinished"];

解决方案是调用 [self willChangeValueForKey:@"isFinished"]; 仅当您按如下方式设置变量“完成”时:

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

不覆盖 setFinished:

于 2013-06-24T11:14:06.503 回答