CoreData + iCloud + Cascade Delete - wie geht das?

78

CoreDataEntität "A" hat eine Eins-zu-Viele-Beziehung zu einer Sammlung von CoreDataEinträgen "B" unter Verwendung einer Kaskadenlöschregel.

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

Wenn die NSPersistentStoreDidImportUbiquitousContentChangesNotificationBenachrichtigung in Gerät 1 empfangen wird, ruft der App-Delegierte an mergeChangesFromContextDidSaveNotificationund sendet dann eine interne Benachrichtigung, die vom Ansichtscontroller erfasst wird und die Details des Eintrags "B" enthält (der Code verwendet, performBlockwo er sollte).

Obwohl der Eintrag "A" tatsächlich ungültig wird, wenn der Detailansichts-Controller die interne Benachrichtigung empfängt, ist der Eintrag "B" weiterhin als gültiges CoreDataObjekt vorhanden. Es scheint, dass die Cascade-Regel ihren Betrieb 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, die Cascade-Regel jedoch noch nicht abgeschlossen ist.

Ich habe versucht, den Eintrag "B" zu aktualisieren, wenn die Benachrichtigung eintrifft, während der stalenessIntervalKontext des verwalteten Objekts vorübergehend auf Null gesetzt wurde, damit kein zwischengespeichertes Objekt verwendet wird. Ich erhalte jedoch weiterhin einen gültigen Eintrag "B" aus dem Geschäft.

Das Überprüfen auf einen nullEintrag "A" an dieser Stelle ist keine Option, da die Situation etwas komplexer ist als die hier beschriebene und ein Nulleintrag "A" in einigen Fällen gültig sein kann.

Ich habe versucht, nach dem Zusammenführen der Änderungen und vor dem Senden der internen Benachrichtigung an die View Controller eine Verzögerung 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 mich 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 Sache? Oder mache ich zuerst etwas falsch?

Amiram Stark
quelle
Es steckt mehr dahinter, als es scheint, da die Kaskadenlöschungen weitergegeben werden, sobald dies zuerst eintritt: processPendingChanges, Speichern oder Beenden eines Run-Loop-Zyklus. Unter normalen Bedingungen sollte das von Ihnen beschriebene Problem nicht bestehen.
Svena
Ist die ID des verwalteten Objekts für das Objekt im Detailansichts-Controller im NSDeletedObjectsKey-Array, das mit der NSPersistentStoreDidImportUbiquitousContentChangesNotification geliefert wird?
ImHuntingWabbits
Passiert das immer oder ist es zeitweise? Ich habe eine komplexe hierarchische Struktur und noch keine Waisenkinder gesehen! Rufen Sie Entität B erneut ab oder behalten Sie möglicherweise einen Verweis auf das Objekt bei, weil Sie es irgendwie anzeigen. Was passiert, wenn Sie die App schließen und erneut öffnen, die Entität B noch vorhanden ist?
Duncan Groenewald
3
@Amiram Eineinhalb Jahre. Hast du deine Antwort bekommen? :)
Hellblauer Punkt

Antworten:

1

Erfahrungsgemäß ist das Abhören anderer Benachrichtigungen NSManagedObjectContextDidSaveNotificationein großes Durcheinander und kann dazu führen, dass Sie sich auf Eigenschaften verlassen, die noch nicht aktualisiert wurden. Der Detailansichts-Controller sollte NSManagedObjectContextDidSaveNotificationBenachrichtigungen abhören , die nach dem Anwenden der Kaskade ausgelöst werden. Sie können dann auf verschiedene Weise ü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 vorhanden ist, niloder Sie können einen Abruf durchführen und feststellen, ob das Objekt im Speicher vorhanden ist).

Leo Natan
quelle