0

コアデータに UIManagedDocument を使用しています。属性を持つ managedObjectContext に Calendar オブジェクトがありcalendarSelectedます。Calendar エンティティには、CalendarEntry との対多関係があります。

属性を変更しcalendarSelected、NSFetchRequest を実行して、次の述語で CalendarEntry オブジェクトを取得すると:

[NSPredicate predicateWithFormat:@"calendar.calendarSelected = YES"]

calendar.calendarSelected は、私が電話をかけずに行った変更を認識していないようです

[myManagedDocument saveToURL:myManagedDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {}];

最初。変更が永続ストアに書き込まれていなくても、同じコンテキストからフェッチすると、そのコンテキストで行われた変更を尊重する必要があることをどこかで読みました。私は何が欠けていますか?

アップデート:

calendarEvents 関係に障害がある場合に発生しているように見えますがcalendarEvents = "<relationship fault: 0x91aec90 'calendarEvents'>";、関係に障害がない場合に機能します。

4

2 に答える 2

1

対多関係で示される、新しく挿入された CalendarEntry オブジェクトでのみ問題が発生する場合は、永続的なオブジェクト ID がまだない可能性があります。これは、オブジェクト ID をダンプし、それが一時的か永続的かを確認するだけで簡単にデバッグできます。

対多関係の包含オブジェクトが保持されている場合に、これが発生するのを見てきました。それが保持されている限り、関係に含まれる対多のオブジェクトは、永続的な ID を取得するようになることはないようです。アプリケーションをバックグラウンドに置いて再起動することで、デバッグがやや簡単になります。通常、バックグラウンド処理により UIManagedDocument が強制的に保存され、CalendarEntry エンティティに永続的な ID が割り当てられてフェッチ可能になるため、その後は期待どおりに機能し始めます。

UIManagedDocument を保存する限り、UIManagedDocument を使用するときにそれがいつ発生するかを制御することはできません。最善の方法は、updateChangeCount:UIDocumentChangeDone を使用して、保存が将来発生するようにスケジュールすることですが、これも「すぐに」発生しますが、決定論的ではありません。つまり、いつ発生するかを知ることはできません。

一時的なオブジェクト ID と永続的なオブジェクト ID の問題を解決するには、それが表示されている場合は、NSManagedObjectContext で次のカテゴリを試してください。問題を強制するために、新しい CalendarEntry オブジェクトの挿入が完了した後に呼び出します。

// Obtain permanent ids for any objects that have been inserted into
// this context.
//
// As of this writing (iOS 5.1), we need to manually obtain permanent
// ids for any inserted objects prior to a save being performed, or any
// objects that are currently retained, that have relationships to the
// inserted objects, won't be updated with permanent ids for the related
// objects when a save is performed unless the retained object is refetched.
// For many objects, that will never occur, so we need to force the issue.

- (BOOL)obtainPermanentIDsForInsertedObjects:(NSError **)error
{
    NSSet * inserts = [self insertedObjects];

    if ([inserts count] == 0) return YES;

    return  [self obtainPermanentIDsForObjects:[inserts allObjects]
                                         error:error];
}
于 2012-04-19T23:52:55.860 に答える
0

基本的に、変更を加えた後は、元にたりマネージャーを使用するか、[document updateChangeCount:UIDocumentChangeDone]を呼び出す必要があります。そしてそれがすべてです!他の「保存」呼び出しは、どこかで何か他のものを壊してしまいます。

更新の標準的な方法は次のようになります...

あなたはあなたがメインスレッドにいることを知っています

NSManagedObjectContext *ctx = document.managedObjectContext;
// Do stuff with it
[document updateChangeCount:UIDocumentChangeDone];

あなたは別のスレッドにいます

[document.managedObjectContext performBlock:^{
    // Do stuff with it on the main thread
    [document updateChangeCount:UIDocumentChangeDone];
}];

また

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.parentContext = document.managedObjectContext;
[moc performBlock:^{
    // Do stuff with it on a background thread
    // Push changes up to parent (which is the document's main MOC)
    // The document will know it's dirty and save changes
    [moc save:&error];
}];

または、メインドキュメントMOCをいじらずにバックグラウンドスレッドで変更を加えたい場合は、親で変更を行います...メインMOCは、次のフェッチまでそれらを認識しません。

[document.parentContext.managedObjectContext performBlock:^{
    // Do stuff with it on a background thread, but the main MOC does not
    // see the changes until it does a fetch.
}];
于 2012-04-12T02:54:51.027 に答える