Frage Was könnte dazu führen, dass mergeChangesFromContextDidSaveNotification Objekte, die aktualisiert wurden, nicht zusammenführt / ungültig macht?


[EDIT: vereinfachte Version der Frage]

  1. mainMOC ist der primäre Kontext des verwalteten Objekts

  2. editorMOC ist ein verwalteter Objektkontext, der in erstellt wurde editorViewController Mit einem Undo-Manager kann der Benutzer ein einzelnes verwaltetes Objekt bearbeiten

  3. nach editorMOC spart, mainMOC aktualisiert das aktualisierte verwaltete Objekt im Benachrichtigungshandler für NSManagedObjectContextDidSaveNotification

  4. Im save Handler, wenn ich benutze [mainMOC refreshObject:obj mergeChanges:YES] Die Aktualisierungen des Objekts werden nicht in reflektiert mainMOC Nachauffrischen Wenn ich benutze [mainMOC refreshObject:obj mergeChanges:NO] Das Objekt wird ungültig gemacht und beim nächsten Fehler werden die Änderungen in den Daten widergespiegelt, die aus dem Speicher geladen werden.

FRAGE: Warum sollte das Objekt das Update nicht wiedergeben? mergeChanges:YES angegeben?

[ORIGINALE FRAGE]

Ich habe eine zentrale datenbasierte App mit mehreren verwalteten Objektkontexten. Die App ist kompliziert und proprietär, sodass ich den Code nicht einfach direkt von der App aus teilen kann. Ich habe eine einfache Test-App erstellt, um mein Problem zu reproduzieren, aber die Test-App weist das Problem nicht auf. Ich war nicht in der Lage, einen logischen Unterschied zwischen den Implementierungen zu finden. Ich entschuldige mich dafür, dass ich keinen Beispielcode gepostet habe. Ich glaube, ich habe die Implementierung unten gut erklärt. Wenn etwas nicht klar ist, bitte fragen Sie in den Kommentaren und ich werde mein Bestes tun, um zu klären.

Hier ist meine Situation. Alles, was unten beschrieben wird, läuft auf dem Hauptthread.

  1. Die App verfügt über einen primären verwalteten Objektkontext namens mainMOC Das ist auf den Haupt-Thread zugegriffen und mit verwendet NSFetchedResultsControllers um Daten in verschiedenen Tabellenansichten anzuzeigen.

  2. Ich habe einen View-Controller angerufen EditorViewController Dies ermöglicht das Bearbeiten eines vorhandenen Objekts einer bestimmten Entität. Dieser View-Controller erstellt seinen eigenen verwalteten Objektkontext namens editorMOC Verwenden des gleichen persistenten Geschäftskoordinators mit einem Rückgängig-Manager, sodass Änderungen rückgängig gemacht oder gespeichert werden können, wenn der Editor abgelehnt wird.

  3. EditorViewController beobachtet die NSManagedObjectContextDidSaveNotification. Wenn diese Benachrichtigung auftritt, ruft der Benachrichtigungshandler auf [_mainMOC mergeChangesFromContextDidSaveNotification:notification] die Änderungen von zusammenführen editorMOC in mainMOC.

  4. Der Tabellenansicht-Controller, der ein NSFetchedResultsController behandelt die Delegiertenmeldungen des Controllers.

Ich habe NSLog-Ausgabe hinzugefügt, um zu sehen, was in all den obigen Schritten passiert, und ich habe Folgendes verifiziert:

  • Ich kann sehen, dass das Objekt geändert und im Editor gespeichert wird.
  • Ich kann das sehen NSManagedObjectContextDidSaveNotification wird aufgerufen und das aktualisierte Objekt ist enthalten.
  • Ich kann sehen, dass der abgerufene Ergebnis-Controller das empfängt controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: Protokollnachricht.
  • Ich kann sehen, dass mainMOC ist nicht spiegelt die Updates wider und das aktualisierte Objekt wurde nicht durch ungültig gemacht mergeChangesFromContextDidSaveNotification:.
  • Wenn ich die App beende und neu starte, wurden die Updates festgeschrieben

Als Referenz implementieren sowohl meine Haupt-App als auch meine Test-App die oben genannten Funktionen. Die Test-App zeigt jedoch an, dass die Updates korrekt zusammengeführt wurden und die Haupt-App nicht.

Ich bin auf der Suche nach Vorschlägen, was das bewirken würde mergeChangesFromContextDidSaveNotification:das aktualisierte Objekt nicht erfolgreich zusammenzuführen und / oder ungültig zu machen.

Vielen Dank!


7
2018-05-09 19:09


Ursprung


Antworten:


Der abgerufene Ergebniscontroller erhält nicht die controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: Nachricht delegieren. Stattdessen wird es als Reaktion auf eine Änderung des Kontexts an den Delegaten gesendet. Wenn diese Delegatenachricht gesendet wird und das richtige Objekt enthält, werden die Änderungen im Hauptkontext erkannt.

Wenn dies der Fall ist, liegt Ihr Fehler höchstwahrscheinlich in dem Code, der den abgerufenen Ergebniscontroller und die Tabellenansicht verbindet. Etwas verhindert, dass das Objekt korrekt angezeigt wird.


2
2018-05-11 03:07



Das Problem, das dazu führte, dass mergeChangesFromContextDidSaveNotification nicht funktionierte, war, dass ich einen neuen NSPersistentStoreCoordinator für jeden neuen NSManagedObjectContext erstellte. Wenn ich NSPersistentStoreCoordinator zwischen allen MOCs freigegeben habe, funktioniert mergeChangesFromContextDidSaveNotification perfekt. Stellen Sie außerdem sicher, dass mergeChangesFromContextDidSaveNotification für den Thread aufgerufen wird, der den MOC besitzt.

Aus den Recherchen, die ich gemacht habe, ist es sicher, NSPersistentStoreCoordinator zwischen Threads zur Verwendung mit NSManagedObjectContext freizugeben. NSManagedObjectContext wird den persistenten Speicher nach Bedarf sperren.


2
2018-03-31 19:22



Eine mögliche Antwort: Sie haben einen dritten MOC, von dem Sie nicht wussten, dass er da war / vergessen hat. (Das ist mir passiert.)

ich hatte

  1. mainMOC
  2. editorMOC
  3. viewerMOC was durch versehentlich fehlgeleitetes Subclassing zustande kam - es sollte sich die Haupt-MOC ansehen, aber stattdessen seine eigenen erstellen und einen eingefrorenen Zustand betrachten. Die "Überprüfung auf Bearbeitungen" -Beziehung ging in die andere Richtung, da erwartet wurde, dass sie in diesem Szenario der "Editor" ist.
  4. Die Benachrichtigung ruft den Rückruf korrekt auf und die Daten werden korrekt in den Haupt-MOC zusammengeführt (was ich erkennen konnte, weil die Daten beim Relaunch korrekt waren)

Hinweis: refreshObject:mergeChanges: wird nicht benötigt. Es ist etwas, das ich auch ausprobiert habe, als es nicht funktionierte, aber die Zusammenführung der Benachrichtigung sollte sich um alle Objekte kümmern, die für Sie bestimmt sind.

- (void)twinStackUpdated:(NSNotification *)notification {
  [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}

nicht sicher, dass das so war Ihre Problem, aber es könnte jemand sein, also ist es da.


0
2018-06-18 03:23



In dem Bemühen, etwas zu akzeptieren, obwohl ich keine definitive Lösung habe, hier ist, was ich getan habe, um dies zu beheben, und das Problem scheint gelöst zu sein.

Ich glaube, das war ein Cache-Problem mit NSFetchedResultsController. Ich habe diesen Code seitdem vereinfacht und sichergestellt, dass jeder NSFetchedResultsController seinen eigenen Cache verwendet. Ich konnte den Aufruf von 'RefreshObject' entfernen und die Dinge scheinen korrekt zu funktionieren.


0
2017-09-26 16:37