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

ste*_*her 4 objective-c key-value-observing

如此实施KVO是否安全:

[self addObserver:self
       forKeyPath:@"restaurant.oldestOrder.patron.frustrationLevel"
          options:0 context:nil];
Run Code Online (Sandbox Code Playgroud)

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

ilu*_*pra 6

执行摘要:

您永远不需要为同一个键添加两次观察者只是因为中间的键发生了变化,NSKeyValueObserving这对您来说就是这样.

只要你的-oldestOrder方法没有返回一个悬空指针,任何东西都不应该破坏.


KVO的工作方式是当您将自己添加为观察者时,观察者将以对象的形式添加到被观察对象的列表中NSObservationInfo.简单.一个NSObservationInfo对象只是一个原始密钥(不是一个路径),对象看,观察者调用,一个指向你传递的上下文,以及其他一些东西记账.

当您观察键的路径时,观察者关系将通过各个NSObservationInfo对象进行观察,这些对象保存在被调用对象的列表中,就好像整个路径是您调用的对象的属性一样-addObserver.

在您的示例中self观察restaurant,但该addObserver:方法然后NSObservationInfo在后台创建对象,这些对象作为观察者添加到路径中的每个相应对象,并且这些对象也会添加到您自己的观察者列表中.

当你观察@"A.B.C.D"的对象,它生成了四个NSObservationInfo对象,每个密钥关系,这些被添加到路径作为观察员在每个按键上,这样你就得到一个NSObservationInfo对象看A的叫,一个看着BA,人看CB,当其中一个NSObservationInfo对象观察到更改时,它会将此传递给原始-addObserver调用方,作为对整个键路径的更改.

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

当路径中间的对象为零或删除时,请-willChangeValueForKey注意这一点并尽可能地将NSObservationInfo对象作为观察者沿着nil'd对象之后的路径移除.这些NSObservationInfo对象仍然存在,并且他们仍然知道他们想要看到什么键,并且在-didChangeValueForKey调用时,它将查看键的新值,如果它具有与其NSObservationInfo对象链正在寻找的键名相匹配的键名,它将把它们作为新的观察者.

因此,当路径中的任何元素@"restaurant.oldestOrder.patron.frustrationLevel"发生更改时,您将收到更改通知,但NSKeyValueObserving机制将尝试在更改后的路径末尾与任何后续更改重新建立与密钥的关系.

这是Cocoatron对此的实现,你可以看到它是如何工作的.