免責事項: 私は完全な CoreData 初心者です。iOS 6.0.1 を搭載した iPhone 4S でアプリを実行しています。
バックグラウンド
私のアプリの一部は、を使用して画像を取得し、UIImagePicker
CoreData を使用してディスクに保存します。上記の画像は、モデル内のアクティビティに関連付けられています。アクティビティは、イメージと 1 対多の関係にあります。
キャプチャ後すぐに画像をディスクに保存し、メモリ不足でフォールトして、表示用のサムネイルを保持する必要があります。そうしないと、比較的少数の画像がキャプチャされた後、iOS がメモリを使いすぎてアプリを強制終了します。
サムネイルだけが必要な場合に、画像全体をメモリに取り込む必要がないように、サムネイルを別のエンティティにしました。サムネイルは、画像と 1 対 1 の関係にあります。また、さまざまな理由から、サムネイル画像データの保存に Core Data を使用していません。代わりに、ファイル名を保存し、ディスク上のファイルを自分で管理します。
これはすべて、ユーザーが少なくとも 1 つの画像を追加した後にアクティビティの追加をキャンセルした場合、ユーザーが追加した画像とサムネイルの両方を削除する必要があることを意味します。
問題
追加した画像オブジェクトを削除しようとすると、2 つのことが起こります。まず、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.}
それで。挿入したことのないオブジェクトを削除しようとしているようです。私だけが私がしたと確信しています。
関係の詳細
アクティビティ <1-*> 画像; ルールの削除: カスケード
--> 逆: 画像 <1-1> アクティビティ。ルールの削除: 無効化
画像 <1-1> サムネイル; 削除規則: カスケード
--> 逆: サムネイル <1-1> 画像。ルールの削除: 無効化
関連コード
画像取得:
- (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];
}
概要
どこが間違っているのかわかりません。表示されるエラー メッセージも役に立ちません。さらに悪いことに、エラー メッセージをグーグルで検索しても、有用な結果が得られません。したがって、私はあなたの素晴らしい経験豊富な人々に助けを求めます。