当沿路径的对象可能发生变化时,观察keyPath是否安全?

时间:2013-05-14 00:12:09

标签: objective-c key-value-observing

实施KVO是否安全:

[self addObserver:self
       forKeyPath:@"restaurant.oldestOrder.patron.frustrationLevel"
          options:0 context:nil];

...当您知道oldestOrder可能会更改或变为零时,以前的oldestOrders可能会被取消分配?

1 个答案:

答案 0 :(得分:6)

执行摘要:

由于中间的键已更改,NSKeyValueObserving为您执行此操作,因此您永远不需要为同一个键添加两次观察者。

只要您的-oldestOrder方法没有返回悬空指针,就不会有任何破坏。


KVO的工作方式是当您将自己添加为观察者时,观察者将以NSObservationInfo对象的形式添加到被观察对象的列表中。简单。 NSObservationInfo对象只是一个原始键(不是路径),要监视的对象,要调用的观察者,指向您传递的上下文的指针,以及其他一些簿记内容。

当您观察键的路径时,观察者关系将通过相应的NSObservationInfo对象进行观察,这些对象保存在被调用对象的列表中,就像整个路径是您调用的对象的属性一样{ {1}}。

在您的示例-addObserver中观察self,但restaurant方法然后在后台创建addObserver:个对象,这些对象作为观察者添加到路径中的每个相应对象,这些也被添加到你自己的观察者名单中。

当您观察对象的NSObservationInfo时,它会创建四个@"A.B.C.D"个对象,每个关键关系一个,并且这些对象作为观察者添加到路径上的每个键中,因此您获得{ {1}}对象正在观看被叫NSObservationInfo,一个正在观看NSObservationInfo A,一个正在观看B A等。当其中一个为NSObservationInfo时对象观察到更改,它将此传递给原始C调用方,作为对整个键路径的更改。

(这是一个实现细节,但它应该有助于解释。)

当路径中间的对象为nil'd或被移除时,B会注意到这一点并尽可能地将-addObserver个对象作为观察者移除,沿着nil'd对象之后的路径移除。这些-willChangeValueForKey对象仍然存在,并且他们仍然知道他们想要看到哪些键,并且当调用NSObservationInfo时,它将查看键的新值以及它是否具有与之匹配的键名称它是NSObservationInfo个对象链正在寻找的东西,它会将它们作为新观察者附加。

因此,当路径-didChangeValueForKey中的任何元素发生更改时,您将收到更改通知,但NSObservationInfo机制将尝试在该路径的末尾重新建立与该键的关系。改变,以及随后的任何改变。

这是Cocoatron's implementation of this,你可以看到它是如何运作的。