我有一个NSArrayController链接到Core Data对象,设置为Auto Rearrange Content并按谓词过滤。一切顺利,直到我试图取消关系并指定另一个关系。此时,我的应用程序崩溃,我收到以下错误:
无法移除观察者 对于 关键路径“career.type” 来自Object,很有可能 因为关键“职业”的价值 没有适当的KVO就改变了 发送通知。检查 KVO遵守Person类。
从窥探中看来,将我的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。
答案 0 :(得分: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...
}
}