核心数据关系在删除后导致保存错误

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 的数据模型编辑器使用核心数据。

【讨论】:

以上是关于核心数据关系在删除后导致保存错误的主要内容,如果未能解决你的问题,请参考以下文章

删除后尝试保存时核心数据崩溃

核心数据保存竞争条件错误

关系保存时核心数据崩溃

尝试将纬度和经度保存到核心数据会导致访问错误

与核心数据的关系错误

核心数据“数据库出现损坏”——导致此错误的原因是啥?