【问题标题】:Key Value Observe removeObserver when observed object is deallocated释放观察对象时观察removeObserver的键值
【发布时间】:2026-02-04 05:20:16
【问题描述】:

有很多与此主题相关的问题,但没有一个回答我的问题。

当该对象被释放时,我想从该对象中removeObserver。我正在使用 KVO,因为需要观察多个项目,而 NSNotification 在这种情况下会产生巨大的开销。

这是场景:

(多个)对象正在被各种其他对象观察。当observer 被释放时,我可以将其作为观察者移除。但是当observed 被释放时,我需要告诉所有observers 将自己作为观察者移除。如何做到这一点?

【问题讨论】:

    标签: iphone objective-c ios key-value-observing


    【解决方案1】:

    Sailesh 如果对象(观察到的)被解除分配,那么该对象就不能被改变或者它的值不能被改变,所以如果你的观察者正在观察一个被解除分配的对象并且被解除分配的对象永远不会发送任何类型的观察通知那么移除观察者有什么好玩的吗???
    ~~~~~~~~~~~~~~~~~~~~~已编辑~~~~~~~~~~~~~~~~~~~~~~~~ 嘿,我从here 得到了一些东西。这个想法是你观察一个额外的属性,比如alive,并将观察到的dealloc写入alive = NO;,随着这个属性的改变,所有观察者都会得到通知,因此你可以删除所有观察者。


    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~

    【讨论】:

    • 在控制台中看到此错误消息后,您想删除Observer,即使它不好玩:)。 An instance 0xd89f200 of class MyClass was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object.
    • 嗯,这是一个严肃的东西......让我搜索一下我能找到什么......谢谢你的回复:)
    • 感谢您的回答。我看到了那个答案,但我正在寻找更清洁的解决方案。在这种情况下,每个观察者都需要观察额外的 keypath。观察者有没有办法知道被观察者正在被释放,而被观察者不知道任何事情?我知道这是一个很长的镜头,但如果可能的话会非常酷。
    • 这个解决方案的主要问题实际上是每个观察到的变量都必须有一个仅用于此目的的变量 - 在这种情况下为alive
    【解决方案2】:

    我认为这里存在设计问题。被观察对象不应该关心它的观察者。你说你想从被观察对象的 dealloc 方法中移除观察者。但是为什么它会被释放呢?如果仍然观察到它在某处存在所有权,则该对象将不会被释放。良好的设计会导致在调用 dealloc 时没有留下任何观察者。

    想象一个将自己注册为模型对象的观察者的视图。这个模型对象要么保留在视图中,要么保留在控制器中。只要模型对象保留在某处,它就不会称其为 dealloc。只有当最后一个所有权被释放时,它才应该调用dealloc。所以说所有的所有权都被释放了,除了视图/视图控制器并且只剩下一个观察者(视图)。现在,在视图/视图控制器释放其对模型对象的所有权之前,它还应该将视图作为观察者移除。所以到调用 dealloc 方法时,应该已经没有观察者了。

    【讨论】:

    • 考虑两个对象互相观察的情况。您建议的设计将创建一个保留周期。在任何情况下,观察者可能只有对被观察者的弱引用,否则考虑到应用程序的所有其他方面,这样做可能不是好的设计。
    • 在我看来,两个对象互相观察是一种糟糕的设计。
    • 感谢您的回答。我意识到我对模型拥有弱所有权的决定是错误的。我现在切换到牢固的关系,希望我现在不会看到很多 KVO 崩溃。
    【解决方案3】:

    当观察到被释放时,您可以单独从-(void)dealloc 发布通知。收到所有其他观察者后,将删除所需的通知。

    【讨论】:

    • 不会有这么多通知,整个使用kvo的目的就落空了。此外,它最终会像: 1. 观察对象的某些属性。 2. 从所有观察到的对象中,在释放时触发通知。 3. 监听释放通知并移除观察者。那是很多工作。没有一些干净的解决方案吗?