【问题标题】:cocoa - Subtle difference between -removeObserver:forKeyPath: and -removeObserver:forKeyPath:context:?可可 - -removeObserver:forKeyPath: 和 -removeObserver:forKeyPath:context: 之间的细微差别?
【发布时间】:2013-05-29 02:21:38
【问题描述】:

短版:

-removeObserver:forKeyPath:有什么用?

为什么不总是使用-removeObserver:forKeyPath:context:

加长版

在开发 Cocoa 程序时,我发现使用 -removeObserver:forKeyPath: 可能(但并非总是)导致如下错误:

Cannot remove an observer <ObservedClass 0x1001301d0> for the key path "exampleKeyPath" from <__NSCFConstantString 0x100009138> because it is not registered as an observer.

虽然使用-removeObserver:forKeyPath:context: 会正常工作。

由于需要在设置观察时指定上下文(使用-observeValueForKeyPath:ofObject:change:context:),我对为什么存在context:-less 删除方法感到困惑。

根据我对NSKeyValueObserving Protocol 的阅读,我认为删除可能适用于所有 上下文中的指定观察者和指定键路径,但-removeObserver:forKeyPath: 失败(没有上下文) 作为-removeObserver:forKeyPath:context: 的替代品(使用NULL 的上下文)似乎否定了这个想法。

那么:为什么我会出现这个错误? -removeObserver:forKeyPath: 对上下文有什么作用?它与配备context: 的弟弟有什么不同?

代码示例

有问题的代码:

-(void) invalidate {
    [(id)observedObject removeObserver:self
                            forKeyPath:@"exampleKeyPath"];
}

非问题代码:

-(void) invalidate {
    [(id)observedObject removeObserver:self
                            forKeyPath:@"exampleKeyPath"
                            context:NULL];
}

【问题讨论】:

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


    【解决方案1】:

    短版:-removeObserver:forKeyPath:context: 仅在 10.7 中引入,因此两者都有。

    长版:为什么会出现错误?在您的代码或系统中看起来像一个错误(我从未见过错误并且经常使用较短的版本)。这两种方法的描述并不表明应该有任何区别。如果没有其他人提出解释,而您在代码中找不到任何内容,请向 Apple 报告错误。

    【讨论】:

      【解决方案2】:

      文档对新方法的使用进行了很好的讨论:

      检查上下文中的值,您可以准确确定使用哪个 addObserver:forKeyPath:options:context: 调用来创建观察关系。当同一个观察者多次为同一个键路径注册,但使用不同的上下文指针时,应用程序可以明确地确定要停止观察哪个对象

      这只是一种更具体地说明您想从对象中删除的哪个绑定的方法。例如,我可能会绑定到一个键路径两次,但使用不同静态变量的内存位置,有点像dispatch_once() 的工作方式。在 10.7 推出并填补了这一空白之前,上下文无关订阅方法是绑定到对象的唯一方法。

      至于您的 KVO 问题,问题可能出现在许多不同的情况下。最常见的是您订阅了一个线程,然后很快从另一个线程中删除了订阅。有时会发生这种情况,因为您尝试观察的对象即将解除分配,这意味着您将订阅一些恰好填充您需要的内存位置的虚假内存位置,然后从该垃圾指针中删除订阅是不可能的。无论哪种方式,请务必监控您使用绑定的方法,因为如果以错误的方式使用它们可能会有点不稳定。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-28
        • 2011-04-26
        • 1970-01-01
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 2020-11-22
        • 2013-06-22
        相关资源
        最近更新 更多