我正在开发一个Cocoa-Touch应用程序,它使用CoreData并且有一些由XCode模型编辑器生成的NSPersistentObject子类。
我注意到最近,在保存上下文时,我收到一个错误,其中包含以下部分的用户信息:
(gdb) po ui {
"Dangling reference to an invalid object." = <null>;
NSAffectedObjectsErrorKey = <dump #1 of someObject>;
NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1550.)";
NSValidationErrorKey = <someKey pointing to someObject #1>;
NSValidationErrorObject = <dump #2 of someOtherObject which points to the dump #1 object>;
NSValidationErrorValue = { <list of someMoreObjects> };
}
用户信息词典中有其他键。
我得到的所有转储都是有效的对象,我已经对它们进行了全部验证。
NSValidationErrorObject
是一个对象,其NSSet
包含NSAffectedObjectsErrorKey
和NSValidationErrorValue
中转储类型的对象。但所有这些对象都是有效的。
此外,这种情况是随机发生的,有时会发生,有时则不会发生,有时候NSValidationErrorValue
中的列表会更长,有时更短。
我不知道为什么会发生这种情况,或者究竟是什么错误。有谁知道发生了什么?什么可能导致这个奇怪错误的想法?
答案 0 :(得分:25)
这种错误通常是因为当一个物体没有必要的互惠关系时经常设置不正确的关系。该对象是“悬空”,因为对象图表示它应该处于一种关系中,但它只是在空间中悬挂而未连接到任何其他对象。该对象在内部一致的意义上仍然有效,但它不在图中的有效位置。
答案 1 :(得分:18)
这个问题有一段时间被问到,但我刚刚遇到它。在我的情况下,在技术上不适当地设置关系。这是由于在不同的上下文中创建的对象设置,请注意不是在同一线程上的不同上下文中的不同线程上。
如果您正在使用Core Data的线程做任何事情,那么请查找线程问题。
答案 2 :(得分:11)
假设您有一个表“食谱”和一个子表“成分”。然后,您可以创建从配方到配料的一对多关系,并创建从配料到配方的反向关系(一对一)。从配方表中指定“级联”的删除规则是有意义的,因为如果删除配方,则还应删除配方。但是,如果在删除规则中对成分中的一对一关系指定“无操作”,则在尝试删除成分时将获得悬空引用错误。将一对一关系上的删除规则更改为“nullify”,这应该可以解决问题。
答案 3 :(得分:5)
我知道事情已经很久了,但我一直在核心数据模型上解决这个问题,其中所有关系都设置为Nullify。保持获取这些悬空引用,直到我在添加关系时找到一个setPrimitiveValue
而不是setValue
。小心,关系,你必须确保你做正确的事情让Core Data维护你的关系!
答案 4 :(得分:3)
我有另一个如何导致此问题的示例:我有一个并发类型为NSMainQueueConcurrencyType
的MOC。代码中的某处我这样做:
__block MyObjectType1 *obj1;
[managedObjectContext performBlockAndWait:^{
obj1 = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:managedObjectContext];
}];
// some other stuff
[self saveContext];
__block NSManagedObjectID *object1ID;
[managedObjectContext performBlockAndWait:^{
object1ID = [obj1 objectID];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// do some slow-ish stuff
[managedObjectContext performBlockAndWait:^{
// create new object that has a relationship
NSManagedObject *obj1_copy = [managedObjectContext objectWithID:object1ID];
MyObjectType2 *obj2 = [NSEntityDescription insertNewObjectForEntityForName:@"OtherThing" inManagedObjectContext:managedObjectContext];
obj2.relatedThing = obj1_copy;
}];
[self saveContext];
});
事实证明有时候,这就失败了。我仍然不明白为什么,但强迫获得非临时 objectID
似乎可以解决问题:
[context performBlockAndWait:^{
NSError *error;
[managedObjectContext obtainPermanentIDsForObjects:@[obj1] error:&error];
object1ID = obj1.objectID;
}];
答案 5 :(得分:1)
我有同样的问题,最后我发现问题是我在两个不同的托管对象上下文之间设置关系。
答案 6 :(得分:0)
使用此代码解决了我的问题:
[[CustomManagedObject managedObjectContext] performBlockAndWait:^{
NSError *error;
if (![[CustomManagedObject managedObjectContext] save:&error])
{
NSLog(@"Error in Saving: %@", [error.userInfo description]);
}
}];
答案 7 :(得分:0)
添加原始答案,可能有几个原因导致此崩溃。仔细阅读错误描述,在我的情况下,我正在与另一个上下文中的对象建立关系。
答案 8 :(得分:0)
我遇到了这个问题,问题与有关系的实体的不同(或者说是一个零)托管对象上下文有关。在我的例子中,当两个实体都有无管理对象上下文时,我创建了一个实体之间的关系,然后将其中一个实体添加到MOC中,并假设另一个实体也被添加到MOC中。我之所以这么做是因为对SO thread的最高答案的前两个评论,但结果是错误的。
所以吸取了教训:如果将实体添加到MOC,则与其有关系的其他实体不会随之拖入MOC。您还必须将它们添加到MOC,否则Core Data将不会满意。