【问题标题】:Multiple KVO Keys: Why call willChangeValueForKey: twice before didChangeValueForKey:?多个 KVO 键:为什么在 didChangeValueForKey: 之前调用 willChangeValueForKey: 两次?
【发布时间】:2015-09-08 14:28:26
【问题描述】:

我一直在尝试修复我们的 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)/

【问题讨论】:

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


    【解决方案1】:

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

    如果你这样做:

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

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

    【讨论】:

    • 有趣。似乎这种模式需要了解 NSOperation 内部观察者如何处理状态变化。你知道这方面是否有进一步的文件吗?
    • 你的意思是操作队列如何观察它的操作?不一定是这样。其他东西可以观察操作属性。我写的是一般情况。不,我没有关于队列如何观察其操作并响应这些变化的更多文档。
    • 不在 NSOperationQueue 级别。我假设当一个 NSOperation 被初始化时,它也会在自己身上私下设置 KVO。我之所以做出这个假设是因为我在堆栈跟踪崩溃[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:] 中看到了这个调用。
    【解决方案2】:

    我在不遵循模式的情况下实现了 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 2020-07-09
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      相关资源
      最近更新 更多