1

我有一个 NSArrayController 链接到核心数据对象,设置为自动重新排列内容并由谓词过滤。一切都很好,直到我试图取消一段关系并分配另一个。那时,我的应用程序崩溃并且我收到以下错误:

无法从 Object 中删除键路径“career.type”的观察者,很可能是因为键“career”的值已更改而未发送适当的 KVO 通知。检查 Person 类的 KVO 兼容性。

通过窥探,似乎将我的 NSArrayController 设置为 Auto Rearrange Content 会导致此问题。但我正在尝试解决问题,而不必求助于手动重新排列 NSArrayController。这是触发错误的伪代码:

object.career = nil;
object.field = (Field *)item;

这是我的 NSArrayController 使用的谓词:

(career != NIL && career == %@) || (field != NIL && field == %@)

其中两个实例的 %@ 是一个 CoreData 对象。

基本上,看起来 NSArrayController 为 object.career.type 设置了一个观察者,并且当该观察者被自动删除时,使关系无效会导致问题。所以我想知道我是不是走错了路?我是否应该获取对象的副本,将其从 MOC 中删除并重新插入,并将职业设置为 nil 并相应地设置字段?

如何正确通知观察者类型已被取消?请注意,这里提到的所有属性和关系都使用 vanilla KVO 兼容的 getter/setter。

4

1 回答 1

4

来自苹果文档

故障和 KVO 通知

当 Core Data 将一个对象变为故障时,会为对象的属性发送键值观​​察 (KVO) 更改通知(请参阅键值观察编程指南)。如果您正在观察变成故障的对象的属性并且随后实现了故障,您会收到其值实际上没有更改的属性的更改通知。

尽管从您的角度来看,这些值在语义上没有改变,但内存中的文字字节会随着对象的具体化而改变。从指针比较的角度考虑,键值观察机制要求 Core Data 在值发生变化时发出通知。KVO 需要这些通知来跟踪关键路径和依赖对象的变化。


所以基本上你会收到一个通知,告诉你有变化,即使不是。因此,您必须检查对象是否已成为故障。然后删除旧的观察者并将新的观察者添加到同一路径......

对我来说这有效(示例代码):

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

    if ([keyPath isEqualToString:@"pageIndex"]) {

        // basically remove the observer from the fault object and assign the new
        if([object isFault]) {
            [object removeObserver:self forKeyPath:@"pageIndex"];
            [the_current_instance_returned_by_core_data addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionOld context:NULL];
        } 

        // do whatever you want to do on change...

    }
}
于 2011-05-20T07:49:48.747 回答