4

我有一个查询核心数据实体“MyGalleryPhoto”的 NSFetchedResultsController。

我正在尝试删除一些对象,并遇到一些问题。我正在使用 MagicalRecord。这是我对代码的最初尝试,在我看来应该可以正常工作。在代码运行时,对象肯定存在,因为它们显示在 fetchedResultsController 中。

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {

    for (MyGalleryPhoto *myGalleryPhoto in [self.fetchedResultsController.fetchedObjects objectsAtIndexes: self.selectedIndexes]) {

        NSError *error = nil;
        MyGalleryPhoto *localMyGalleryPhoto = (MyGalleryPhoto *) [localContext existingObjectWithID: myGalleryPhoto.objectID error: &error];

        NSLog(@"error: %@:%@", [error localizedDescription], [error userInfo]);
        NSLog(@"mygp: %@", [localMyGalleryPhoto description]);

        [localMyGalleryPhoto deleteInContext: localContext];
    }

} completion:^(void){
}];

此代码不起作用。找不到 myGalleryPhoto 条目,返回的错误是:“操作无法完成。(Cocoa 错误 133000。)”我也尝试使用 MR_inContext,它只调用 existingObjectWithId:error:。

经过一番折腾,我想出了这个邪恶的科学怪人的怪物,它从实体中获取所有记录并比较 ObjectID 的字符串表示形式。这工作正常。为什么?我正在使用我今天从 GitHub 下载的 MagicalRecord 副本、最新的 XCode、最新的 SDK 等等。

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {

    NSArray *allMyGalleryPhotos = [MyGalleryPhoto findAllInContext: localContext];

    for (MyGalleryPhoto *myGalleryPhoto in [self.fetchedResultsController.fetchedObjects objectsAtIndexes: self.selectedIndexes]) {

        MyGalleryPhoto *myGalleryPhotoToDelete = nil;

        for (MyGalleryPhoto *existingMyGalleryPhoto in allMyGalleryPhotos) {

            NSString *existingURLString = [[existingMyGalleryPhoto.objectID URIRepresentation] absoluteString];
            NSString *URLString = [[myGalleryPhoto.objectID URIRepresentation] absoluteString];

            NSLog(@"ExistingURLString: %@", existingURLString);
            NSLog(@"URLString: %@", URLString);

            if ([URLString isEqualToString: existingURLString]) {
                myGalleryPhotoToDelete = existingMyGalleryPhoto;
            }
        }

        if (myGalleryPhotoToDelete) [myGalleryPhotoToDelete deleteInContext: localContext];

    }

} completion:^(void){
}];
4

1 回答 1

5

Cocoa Error 13000 是参照完整性错误,如文档中所述。这意味着您正在寻找商店中不存在的对象。在更实际的层面上,这意味着您的上下文(我假设您有多个托管对象上下文)不同步。也就是说,您已将一个新对象添加到一个上下文中,而另一个没有该对象,因为之前的上下文尚未保存。

关于您的代码,我在第一个示例中看到的第一个问题是您从一开始就跨越了线程边界。fetchedResultsController 引用了另一个上下文中的对象(我将假设默认上下文)。每次调用 saveInBackground 时,它都会为您提供一个新的上下文来使用,但它也会将该代码块放在后台线程上。跨越线程边界,即使在新版本的 Core Data 中,也会让你发疯,难以随机追踪问题。

如果您在第一个(更简单的)代码块中尝试做的事情是您有一组要从应用程序中删除的照片对象,那么要点是。我会做这样的事情:

NSPredicate *objectsToDelete = [NSPredicate predicateWithFormat:@"self in %@", self.fetchedResultsController.fetchedObjects];

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *)localContext
{
     [MyGalleryPhoto deleteAllMatchingPredicate:objectsToDelete inContext:localContext];
}];

deleteAllMatchingPredicate 方法应该在正确的上下文中查找对象(您在第一个代码块中没有这样做),以便可以删除它们。它还将对象设置为错误加载,因此我们不会将所有内容加载到内存中,只会立即删除它。它只会加载它需要的东西,而不是更多。

在这种情况下,我不会使用 existingObjectWithID:。此方法从不加载故障。您的用例意味着它将整个对象加载到内存中,但无论如何都要删除它。

于 2012-07-04T18:37:38.120 回答