4

CoreDataエンティティ「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)」また、existingObjectWithId:error:を呼び出すMR_inContextを使用してみました。

多くのことをいじった後、私はこの下品なフランケンシュタインの怪物を思いついた。それはエンティティからすべてのレコードを取り出し、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 エラー 13000 は参照整合性エラーであり、ドキュメントで説明されています。つまり、ストアに存在しないオブジェクトを探しているということです。より実用的なレベルでは、これはコンテキスト (複数の管理対象オブジェクト コンテキストがあると想定しています) が同期していないことを意味します。つまり、1 つのコンテキストに新しいオブジェクトを追加しましたが、前のコンテキストが保存されていないため、別のコンテキストにはそのオブジェクトがありません。

あなたのコードに関して、最初の例で最初に目にする問題は、最初からスレッドの境界を越えていることです。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 に答える