2012-05-11 12 views
78

CoreData Entität "A" hat eine Eins-zu-viele-Beziehung zu einer Sammlung von CoreData Einträge "B", die eine Cascade-Löschregel verwenden.CoreData + iCloud + Cascade Löschen - wie geht das?

In einer iCloud Umgebung, während Gerät 1 eine Detailansicht eines der "B" Einträge zeigt, löscht Gerät 2 den "A" Eintrag.

Wenn die NSPersistentStoreDidImportUbiquitousContentChangesNotification Benachrichtigungsgerät 1 empfangen wird, dessen AppDelegate ruft mergeChangesFromContextDidSaveNotification und sendet dann eine interne Benachrichtigung, die durch die View-Controller erfasst die Details Eintrag „B“ zeigt (der Code verwendet performBlock wo es sollte).

Obwohl der Eintrag "A" tatsächlich ungültig wird, wenn der Detailansicht-Controller die interne Benachrichtigung empfängt, ist der Eintrag "B" weiterhin als gültiges Objekt CoreData vorhanden. Es scheint, dass die Cascade-Regel ihre Operation noch nicht abgeschlossen hat. Daher ist dem View-Controller in Gerät 1 das Löschen nicht bekannt, was zu unerwarteten Ergebnissen führen kann.

mergeChangesFromContextDidSaveNotification scheint vorzeitig zurückzukehren, wenn die Basisdaten zusammengeführt wurden, aber die Cascade-Regel noch nicht abgeschlossen ist.

Ich habe versucht, Eintrag "B" zu aktualisieren, wenn die Benachrichtigung eintrifft, während stalenessInterval des verwalteten Objektkontexts vorübergehend auf Null festgelegt wird, so dass ein zwischengespeichertes Objekt nicht verwandt wird, aber ich einen gültigen Eintrag "B" von dem Geschäft.

Überprüfung für einen null Eintrag „A“ an dieser Stelle ist keine Option, weil die Situation etwas komplexer ist als das, was ich hier beschrieben und ein Null-Eintrag „A“ kann in einigen Fällen gültig sein.

Ich habe versucht, eine Verzögerung nach dem Zusammenführen der Änderungen und vor dem Senden der internen Benachrichtigung an die View-Controller einzuführen. Ich fand heraus, dass eine Verzögerung von 2 Sekunden nicht hilft, aber eine Verzögerung von 10 Sekunden funktioniert.

Aber ich möchte nicht auf diese Verzögerung verlassen. Dies ist eine Testumgebung ohne viele Daten, und ich weiß nicht, was in einer Produktionsumgebung passieren wird. Sich auf eine experimentelle Verzögerung zu verlassen, scheint nicht das Richtige zu sein.

Gibt es eine Richtige? Oder mache ich am Anfang etwas falsch?

+0

Es gibt mehr als es scheint, da die Kaskadenlöschungen weitergegeben werden, sobald das, was zuerst kommt: processPendingChanges, speichern oder Ende einer Laufschleife Zyklus. Unter normalen Bedingungen sollte das von Ihnen beschriebene Problem nicht bestehen. – svena

+0

ist die verwaltete Objekt-ID für das Objekt in den Detailansicht-Controller in der NSDeletedObjectsKey Array, das mit dem NSPersistentStoreDidImportUbiquitousContentChangesNotification kommt? – ImHuntingWabbits

+0

Tritt dies immer oder intermittierend auf? Ich habe eine komplexe hierarchische Struktur und habe noch keine Waisenkinder gesehen! Holen Sie Entität B erneut, oder könnte es sein, dass Sie einen Verweis auf das Objekt behalten, weil Sie es irgendwie anzeigen. Was passiert, wenn Sie die App schließen und wieder öffnen, die Entität B immer noch da? –

Antwort

1

Aus Erfahrung ist das Abhören anderer Benachrichtigungen als NSManagedObjectContextDidSaveNotification ein großes Durcheinander und kann dazu führen, dass man sich auf Eigenschaften verlässt, die noch nicht aktualisiert wurden. Der Detailansicht-Controller sollte auf NSManagedObjectContextDidSaveNotification Benachrichtigungen hören, die ausgelöst werden, nachdem die Kaskadierung angewendet wurde. Sie können dann auf verschiedene Arten überprüfen, ob das aktuelle Objekt gültig ist oder nicht (Sie können überprüfen, ob der Kontext des verwalteten Objekts des aktuellen Objekts nil ist oder Sie können einen Abruf durchführen und feststellen, ob das Objekt im Speicher vorhanden ist).