实施KVO是否安全:
[self addObserver:self
forKeyPath:@"restaurant.oldestOrder.patron.frustrationLevel"
options:0 context:nil];
...当您知道oldestOrder
可能会更改或变为零时,以前的oldestOrders
可能会被取消分配?
答案 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,你可以看到它是如何运作的。