Core Data 无法删除从未插入的对象错误

Posted

技术标签:

【中文标题】Core Data 无法删除从未插入的对象错误【英文标题】:Core Data cannot delete object that was never inserted error 【发布时间】:2012-11-20 08:51:01 【问题描述】:

免责声明:我完全是 CoreData 菜鸟。我在装有 ios 6.0.1 的 iPhone 4S 上运行我的应用程序。

背景

我的应用程序的一部分使用UIImagePicker 获取图像并使用CoreData 将它们保存到磁盘。所述图像与模型中的活动相关联。活动与图像具有一对多的关系。

我需要在捕获图像后立即将图像保存到磁盘,然后将它们排除在内存之外,保留缩略图以供显示。如果我不这样做,iOS 会在捕获相对较少数量的图像后,因为占用过多内存而终止我的应用程序。

我将缩略图设为一个单独的实体,以避免在我只需要缩略图的情况下将整个图像放入内存中。缩略图与图像具有一对一的关系。另外,由于各种原因,我没有使用 Core Data 来存储缩略图数据;相反,我存储文件名,并自己管理磁盘上的文件。

所有这一切意味着,如果用户在添加了至少一张图片后取消添加活动,那么用户添加的图片和缩略图都需要删除。

问题

当我尝试删除添加的图像对象时,会发生两件事。首先,Core Data 抱怨我的删除规则:

Core Data: annotation: repairing missing delete propagation for to-one relationship image on object <Thumbnail: 0x1dd4d9e0> (entity: Thumbnail; id: 0x1dd4d410 <x-coredata:///Thumbnail/tE7E99D89-C986-4287-ABBD-C6BA7006E9264> ; data: 
    activity = nil;
    fileName = "ECD70C72-745A-4959-BF41-586E9521F1D6";
    image = "0x1dd9f960 <x-coredata:///Image/tE7E99D89-C986-4287-ABBD-C6BA7006E9263>";
) with bad fault 0x1dd9f960 <x-coredata:///Image/tE7E99D89-C986-4287-ABBD-C6BA7006E9263>

其次,当我尝试保存托管对象上下文时,保存失败,Core Data 抛出异常。这是 NSError 对象的输出:

Error Domain=NSCocoaErrorDomain Code=134030 "The operation couldn’t be completed. (Cocoa error 134030.)"
 UserInfo=0x1f0ca270 NSAffectedObjectsErrorKey=(
    "<Image: 0x1dd9f910> (entity: Image; id: 0x1dd9f960 <x-coredata:///Image/tE7E99D89-C986-4287-ABBD-C6BA7006E9263> ;
         data: 
             activity = nil;
             image = nil;
             thumbnail = nil;
         )"
), NSUnderlyingException=Cannot delete object that was never inserted.

所以。显然我正在尝试删除我从未插入的对象?只有我很确定我做到了。

关系详情

活动 图像;删除规则:级联 --> 逆:图像 Activity;删除规则:无效

图像 缩略图;删除规则:级联 --> 反转:缩略图 图像;删除规则:无效

相关代码

图像采集:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

    UIImage* acquiredImage = (UIImage*)info[UIImagePickerControllerEditedImage];
    if (!acquiredImage)  
        acquiredImage = (UIImage*)info[UIImagePickerControllerOriginalImage];
    

    // Save the image to disk so we can fault it and free up its memory
    NSManagedObjectContext* moc = [(ATAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
    Image* imageToSave = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:moc];
    Thumbnail* thumbToSave = [NSEntityDescription insertNewObjectForEntityForName:@"Thumbnail" inManagedObjectContext:moc];
    [addedImageManagedObjects addObject:imageToSave];
    [addedThumbnailManagedObjects addObject:thumbToSave];

    [thumbToSave setThumbnailImage:acquiredImage];
    imageToSave.thumbnail = thumbToSave;

    NSError* error;
    [moc save:&error];
    // TODO: error handling

    // I know it doesn't look it, but this call will turn the imageToSave into a fault, thus freeing up its memory
    [moc refreshObject:imageToSave mergeChanges:NO];

    // NOW, we can add the thumbnail image to our collection view
    // NOTE, -thumbnailImage is a method on my Thumbnail NSManagedObject subclass
    [self addImage:[thumbToSave thumbnailImage] toCollectionView:imageDisplayView];

    [self dismissModalViewControllerAnimated:YES];

取消处理程序:

- (IBAction)cancel:(id)sender 
    NSManagedObjectContext* moc = [(ATAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];

    // Delete any images we saved to disk
    // Note that the activity object's changes get discarded b/c they were made on the child managed object context
    // (We couldn't do that for images b/c we needed them to be written to disk and then faulted out of memory)
    for (Thumbnail* thumb in addedThumbnailManagedObjects)  
        // This method deletes the thumbnail image file whose storage I am managing myself
        [thumb deleteThumbnailFile];
        // I shouldn't have to explicitly delete the thumbnail since the delete of its image should cascade down...right?
    
    for (Image* image in addedImageManagedObjects)  
        [moc deleteObject:image];
    

    NSError* error;
    if (![moc save:&error])  
        NSLog(@"%@", error);
    
    // TODO: error handling

    [self resetToPristineState];
    [self.presentingViewController dismissModalViewControllerAnimated:YES];

总结

我看不出哪里出错了,我收到的错误消息也没有帮助。更糟糕的是,谷歌搜索错误消息并没有给我任何有用的结果。因此,我向各位经验丰富的优秀人士寻求帮助。

【问题讨论】:

【参考方案1】:

哦。天啊。这个错误太愚蠢了。我很惭愧。

好的。请注意,在我的图像采集处理程序中,我从未设置 Image 托管对象的图像数据?是的。事实证明你需要这样做。 :)

无论如何,我已经解决了我自己的问题。

【讨论】:

我知道。只要系统允许,我就会去做。

以上是关于Core Data 无法删除从未插入的对象错误的主要内容,如果未能解决你的问题,请参考以下文章

通过 RestKit 发布 ManagedObject 会导致“无法更新从未插入的对象”

使用 Core Data 获取生成“无法识别的选择器错误”?

“Core Data 无法为......”

Core Data 中的拒绝规则无法正常工作

Core Data + iCloud,更改通知插入和删除关系中的对象但不更新关系中现有实体的属性

从 SQL Server ColumnStore 中删除会出现“无法插入重复键”错误