Wie Sie Änderungen in mergeChangesFromContextDidSaveNotification in NSManagedObjectContextWillSaveNotification ignorieren

8

Ich verwende einen Private Managed Object Context, um einige neue Objekte im persistenten Speicher anzulegen, und dann nach dem Speichern des privaten MOC, indem Sie sie mit mergeChangesFromContextDidSaveNotification in den Haupt-MOC zusammenführen. Dies funktioniert einwandfrei und aktualisiert die Benutzeroberfläche nach Bedarf, und NSManagedObjectContextWillSaveNotification wird hier NICHT für mainMOC aufgerufen.

Dann mache ich einige Änderungen an der mainMOC über die Benutzeroberfläche und höre NSManagedObjectContextWillSaveNotification . Die Benachrichtigung wird gepostet, aber sie enthält nicht nur die von mir vorgenommenen Änderungen, sondern auch die Objekte, die mit PrivateMOC aus mergeChangesFromContextDidSaveNotification zusammengeführt wurden.

Gibt es eine Möglichkeit, die Änderungen, die aus einem anderen Kontext in die mainContext eingefügt wurden, bei nachfolgenden contextDidChange Benachrichtigungen zu ignorieren?

Hier ist das Setup:

%Vor%

Dies funktioniert gut und speichert den privaten Kontext und das Zusammenführen in mainContext löst keine contextWillSave -Benachrichtigung aus. Aber beim Bearbeiten der Daten von der UI (auf der Haupt-MOC) löst die Benachrichtigung und enthält die Daten, die zuvor mit dem privaten MOC gespeichert wurde.

Hoffe, das ist klar. Lassen Sie mich wissen, ob ich etwas anderes hinzufügen sollte.

- AKTUALISIEREN -

Scheint so, als ob das Problem darin besteht, Objekte aus dem privaten Kontext zu löschen. Nach dem Löschen aus dem privaten Kontext und dem Aufruf von mergeChangesFromContextDidSaveNotification auf dem Haupt-MOC zeigt das deletedObjects -Set von mainMoc immer noch das Objekt an, das gelöscht wurde. Dies geschieht nicht bei Einfügungen oder Aktualisierungen im privaten Kontext. Ist das irgendwo dokumentiert? Was könnte die Problemumgehung sein?

    
Z S 01.03.2016, 21:02
quelle

2 Antworten

2

Ändern von privateContextDidChange gefällt das ...

%Vor%

... wobei PrivateMOC der Verweis auf den Kontext des privaten verwalteten Objekts ist?

    
Markus Schmid 08.03.2016 13:46
quelle
1

Core Data gibt es schon seit einigen Jahren, und während dieser Zeit hat sich das Concurrency-Modell weiterentwickelt.

Die Modelle "Thread Confinement" und "Locking" für Parallelität verwendeten Benachrichtigungen, um Änderungen zwischen Kontexten zu kommunizieren. Wenn ein Kontext gespeichert wurde, wird eine Benachrichtigung mit Informationen über die Änderungen gesendet. Diese Information könnte verwendet werden, um die Änderungen von einem Kontext in andere zusammenzuführen. Dies wurde nie besonders gut skaliert und war oft ein großer Schwachpunkt für Anwendungen. Die Modelle "Locking" und "Thread Confinement" sind seit einigen Jahren veraltet.

Als "Warteschlangenbeschränkung" eingeführt wurde, wurde das Konzept der "verschachtelten Kontexte" eingeführt. Ein Kontext könnte einen übergeordneten Kontext haben, und wenn der untergeordnete Kontext gespeichert wird, werden diese Änderungen automatisch an den übergeordneten Kontext kommuniziert (und nicht weiter). Dies ist die empfohlene Methode, um Änderungen zwischen Kontexten zu kommunizieren, wenn Sie die Warteschlangenbeschränkung verwenden, was Sie auch sind.

Es wird nicht empfohlen, mergeChangesFromContextDidSaveNotification: mit einem NSPrivateQueueConcurrencyType -Kontext zu verwenden.

Core Data führt viele interne Buchhaltungs- und Änderungsnachverfolgungen für Sie durch. Normalerweise werden diese Informationen während einer Sicherungsoperation aggregiert und zusammengeführt - dies ist Teil der Operation processPendingChanges . Wenn die Sicherungsoperation in einem performBlockAndWait: ausgeführt wird, ist dies möglicherweise nicht der Fall oder sie ist nicht vollständig - was dazu führt, dass die Änderungen (und alle Änderungsbenachrichtigungen) unvollständig oder überhaupt nicht durchgeführt werden. performBlockAndWait: ist reentrant, was nicht mit dem Prozess processPendingChanges kompatibel ist. Wenn Sie stattdessen performBlock: verwenden, wird das Verhalten konsistenter.

Wenn Sie verschachtelte Kontexte verwenden, um Änderungen anstelle von Benachrichtigungen zu kommunizieren, wird Ihr Problem, wie Sie es in Ihrer Frage beschreiben, gelöst.

    
quellish 06.03.2016 23:24
quelle