核心数据关系在删除后导致保存错误
Posted
技术标签:
【中文标题】核心数据关系在删除后导致保存错误【英文标题】:Core Data Relationships cause save error after delete 【发布时间】:2009-09-23 00:42:38 【问题描述】:这个问题可能是一个很长的问题。删除实体后保存时,我无法弄清楚我在核心数据项目中遇到的错误。
我有两个主要的实体,一个服装和一个文章。我可以毫无问题地创建它们,但是当我删除它们时,我会收到以下错误日志:
对于服装:
2009-09-22 20:17:37.771 itryiton[29027:20b] Operation could not be completed. (Cocoa error 1600.)
2009-09-22 20:17:37.773 itryiton[29027:20b]
NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1600.)";
NSValidationErrorKey = outfitArticleViewProperties;
NSValidationErrorObject = <Article: 0x12aa3c0> (entity: Article; id: 0x12b49a0 <x-coredata://7046DA47-FCE1-4E21-8D7B-E532AAC0CC46/Article/p1> ; data:
articleID = 2009-09-22 19:05:19 -0400;
articleImage = 0x12b4de0 <x-coredata://7046DA47-FCE1-4E21-8D7B-E532AAC0CC46/ArticleImage/p1>;
articleType = nil;
attributeTitles = "(...not nil..)";
color = nil;
comment = nil;
dateCreated = 2009-09-22 19:05:19 -0400;
designer = nil;
imageView = "(...not nil..)";
location = "(...not nil..)";
outfitArticleViewProperties = (
0x12b50f0 <x-coredata://7046DA47-FCE1-4E21-8D7B-E532AAC0CC46/OutfitArticleViewProperties/p1>
);
ownesOrWants = 0;
pattern = nil;
price = nil;
retailer = nil;
thumbnail = "(...not nil..)";
washRequirements = nil;
wearableSeasons = nil;
);
NSValidationErrorValue = (
<OutfitArticleViewProperties: 0x1215340> (entity: OutfitArticleViewProperties; id: 0x12b50f0 <x-coredata://7046DA47-FCE1-4E21-8D7B-E532AAC0CC46/OutfitArticleViewProperties/p1> ; data:
article = 0x12b49a0 <x-coredata://7046DA47-FCE1-4E21-8D7B-E532AAC0CC46/Article/p1>;
articleViewPropertiesID = nil;
outfit = nil;
touch = nil;
view = "(...not nil..)";
)
);
如果我删除一篇文章,我会得到:
2009-09-22 18:58:38.591 itryiton[28655:20b] Operation could not be completed. (Cocoa error 1560.)
2009-09-22 18:58:38.593 itryiton[28655:20b] DetailedError:
NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1600.)";
NSValidationErrorKey = articleImage;
NSValidationErrorObject = <Article: 0x12aa340> (entity: Article; id: 0x12b3f10 <x-coredata://05340FA6-B5DC-4646-A5B4-745C828C73C3/Article/p1> ; data:
articleID = 2009-09-22 18:58:26 -0400;
articleImage = 0x12b4d00 <x-coredata://05340FA6-B5DC-4646-A5B4-745C828C73C3/ArticleImage/p1>;
articleType = nil;
attributeTitles = "(...not nil..)";
color = nil;
comment = nil;
dateCreated = 2009-09-22 18:58:26 -0400;
designer = nil;
imageView = "(...not nil..)";
location = "(...not nil..)";
outfitArticleViewProperties = (
0x12b5010 <x-coredata://05340FA6-B5DC-4646-A5B4-745C828C73C3/OutfitArticleViewProperties/p1>
);
ownesOrWants = 0;
pattern = nil;
price = nil;
retailer = nil;
thumbnail = "(...not nil..)";
washRequirements = nil;
wearableSeasons = nil;
);
NSValidationErrorValue = <ArticleImage: 0x12ad600> (entity: ArticleImage; id: 0x12b4d00 <x-coredata://05340FA6-B5DC-4646-A5B4-745C828C73C3/ArticleImage/p1> ; data:
article = 0x12b3f10 <x-coredata://05340FA6-B5DC-4646-A5B4-745C828C73C3/Article/p1>;
image = "(...not nil..)";
);
1600 错误是:
NSValidationRelationshipDeniedDeleteError 表示某些关系的错误代码 使用删除规则 NSDeleteRuleDeny 是 非空。
适用于 Mac OS X v10.4 及更高版本。
在 CoreDataErrors.h 中声明。
但我一辈子都看不到哪种关系会阻止删除。如果某个 Core Data 向导能看出我的做法的错误,我会感到谦卑。
我无法将此标记为已解决,因为我并没有真正解决它,但我确实有一个可行的解决方法。在我的每个managedObjects
的.m
中,我添加了一个看起来像这样的方法:
-(void) deleteFromManangedObjectContext
self.outfit = nil;
self.article = nil;
[[self managedObjectContext] deleteObject:self];
所以你可以看到,首先我手动清除了关系,然后我让对象自己删除。在其他对象中,不是nil-ing
,而是在某些对象关系上调用我的删除方法,以获得级联。
【问题讨论】:
更新:我一直在做很多实验。如果我将所有删除规则都设置为“无操作”,那么我就可以删除了。当然,这不是我想要的行为,让一切都处于不一致的状态。如果我的任何关系船设置为 Cascade 或 Nullify,那么我将收到我上面提出的错误。 另一个更新:正如亚历克斯所指出的,此错误旨在传达您将删除规则设置为拒绝。我没有将任何删除规则设置为拒绝。我已经向苹果提交了一份关于错误报告此错误的错误报告。如果他们回应,我会告诉你的。这仍然不能解释我的模型出了什么问题,但正确的错误代码肯定会有所帮助! 另一个更新:我不会放弃这个。我对我的代码进行了一些修改,使我能够删除 OutfitArticleViewProperties。两种关系(服装和文章)的删除规则都是 Nullify。当我尝试删除时,我得到了与以前相同的错误。这提出了一个非常有趣的问题,如果删除规则为 Nullify,怎么会出错?我没有要求它在关系结束时删除对象,只是将关系的目标设置为 nil。 ...哦,在你问之前,是的,这种关系是可选的。 感谢您的努力。我有同样的问题。我检查了我所有的删除规则、覆盖的方法等......问题仍然不时存在。我最终得到了相同的解决方案,但它更像是“变通”,根本不令人满意。 【参考方案1】:我只是遇到了删除失败的问题,并登陆了这个问题。而且我已经弄清楚了我的问题,并认为我也会分享这个问题,也许有人也会遇到同样的问题。
我犯的错误是我试图删除的对象 (A) 与另一个对象 (B) 有关系,其中 NULL 作为删除规则。但是,对象 B 也与 A 有关系,并且它是非可选的。因此,当我删除 A 时,B 与 A 的关系变为 null,这是不允许的。当我将删除规则更改为级联时,它起作用了。
【讨论】:
这对我来说是正确的答案 - 如果您需要对象的反向关系,请确保您(阅读器)xcdatamodeld 文件中的删除规则未设置为“无效”。 冠军!我浪费了整个下午试图解决这个问题,直到我最终得到这个答案。谢谢!【参考方案2】:您是否碰巧自己实现了一些关系访问器? 我曾经有过类似的代码
-(NSSet*)articles
re-calculates properties....
return [self primitiveValueForKey:@"articles"];
在 NSManagedObject 的一个子类中并且有一个保存错误。 发生的情况是,当从 ManagedObjectContext 中删除该对象时,CoreData 调用访问器“articles”来处理删除传播。文章的重新计算发生在删除传播期间,这在我的情况下重新恢复了无效的“文章”。
【讨论】:
我需要为 set 属性设置一个断点,并实现了我自己的 set 方法。这就是让我的存档崩溃的原因。感谢您的提示。【参考方案3】:我无法将此标记为已解决,因为我并没有真正解决它,但我确实有一个可行的解决方法。在我的每个 managedObjects 的 .m 中,我添加了一个如下所示的方法:
-(void) deleteFromManangedObjectContext
self.outfit = nil;
self.article = nil;
[[self managedObjectContext] deleteObject:self];
所以你可以看到,首先我手动清除了关系,然后我让对象自己删除。在其他对象中,不是 nil-ing,而是在某些对象关系上调用我的 delete 方法,以获得级联。
我仍然对“正确”的答案感兴趣。但这是我拥有的最佳解决方案,它确实允许对我的关系如何删除进行一些细粒度的控制。
【讨论】:
【参考方案4】:检查您的 xcdatamodel
文件以获取 Deny
删除规则。单击每个关系,直到找到它。您需要更改此规则或调整删除托管对象的方式,以预测该规则对关系的应用。
【讨论】:
我检查了,我所有的关系都是 Cascade 或 Nullify。【参考方案5】:我最近遇到了这个错误,因为我在 - (void)willSave 方法中有代码,它在 - (BOOL)isDeleted 已经返回 true 之后更新了删除托管对象的一些属性。
我通过以下方式修复它:
- (void)willSave
if (![self isDeleted])
//Do stuff...
【讨论】:
【参考方案6】:我遇到了类似的问题,后来发现问题出在 .xib 文件中。当我打开相关数组控制器的“删除时删除对象”复选框(在 Bindings->Content Set 下)时,问题就消失了。
不知道这对你的情况是否有帮助,但我有很多头发因为问题被隐藏在 Interface Builder 中的某个地方而变得灰白。
【讨论】:
【参考方案7】:在我的例子中,我在我的 NSManagedObject 子类中天真地创建了自定义方法:isDeleted。在删除/重命名它之前,我遇到了奇怪的保存异常。 在失去理智之后,我这次又更彻底地阅读了文档。 事实证明,我重写了 NSManagedObject 方法之一,但不能重写。
检查此文档摘录是否对您有帮助:
不得覆盖的方法
NSManagedObject 本身自定义了 NSObject 的许多特性,以便 托管对象可以正确集成到核心数据中 基础设施。 Core Data 依赖于 NSManagedObject 的实现 以下方法中的一种,因此您绝对不能 覆盖:primitiveValueForKey:,setPrimitiveValue:forKey:, isEqual:, 哈希, 超类, 类, self, isProxy, isKindOfClass:, isMemberOfClass:、conformsToProtocol:、responsToSelector:、 managedObjectContext, entity, objectID, isInserted, isUpdated, isDeleted、isFault、alloc、allocWithZone:、new、instanceRespondToSelector:、instanceMethodForSelector:、 methodForSelector:, methodSignatureForSelector:, instanceMethodSignatureForSelector:, 或 isSubclassOfClass:.
除此之外,还有其他方法可以覆盖,但您必须调用超级实现,例如或调用:willAccessPrimitiveForKey, didAccessPrimitiveForKey
in accessors 和 willChangevalueForKey, didChangeValueForKey
in setters....
【讨论】:
【参考方案8】:在非可选的父子关系上,我遇到了与级联删除非常相似的问题。这很令人困惑,因为我认为父关系删除规则设置为级联。事实证明,Xcode 中的数据模型编辑器没有保存删除规则。我会将其设置为 Cascade,转到不同的视图并返回,它将再次设置为无效。我不得不重新启动 Xcode 并将删除规则设置为级联。在我这样做之后,一切正常。
因此,如果其他人遇到此问题,请仔细检查 Xcode 是否正在保存您的删除规则,然后再深入研究更复杂的解决方案。
顺便说一句,我在 ios 上通过 Xcode 5 的数据模型编辑器使用核心数据。
【讨论】:
以上是关于核心数据关系在删除后导致保存错误的主要内容,如果未能解决你的问题,请参考以下文章