2013-10-18 7 views
6

Ich habe folgende Core Data Setup in meiner App:Core Data: Parent Kontext und Änderungspropagierung

Persistent Store Coordinator 
^Background MOC (NSPrivateQueueConcurrencyType) 
    ^Main Queue MOC (NSMainQueueConcurrencyType) 

Hier ist der Code für die Initialisierung:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[_backgroundContext setPersistentStoreCoordinator:self.coordinator]; 
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
[_mainContext setParentContext:_backgroundContext]; 

ich den Hintergrund MOC verwenden für den Import von großen Datenmengen. Ich verwende es auch, um komplexe Abrufanforderungen im Hintergrund auszuführen und dann die Objekt-IDs an die Hauptwarteschlange zu übergeben, um die Objekte unter Verwendung dieser IDs abzurufen.

Das funktioniert ganz gut. Ich bin mir jedoch nicht sicher, wie ich die Hauptwarteschlange MOC über die Änderungen informieren soll, die im Hintergrund-MOC vorgenommen wurden. Ich weiß, dass, wenn ich eine Abrufanforderung in der Hauptwarteschlange MOC ausführe, die Änderungen erhalten wird, aber das ist nicht das, was ich möchte.

Ist es in Ordnung, die NSManagedObjectContextObjectsDidChangeNotification Benachrichtigung zu verwenden, die durch den Hintergrund MOC bekannt gegeben wird, und mergeChangesFromContextDidSaveNotification: auf der Hauptwarteschlange MOC zu benennen? Dies sollte dann dazu führen, dass die NSManagedObjectContextObjectsDidChangeNotification Benachrichtigung der Hauptwarteschlange MOC ausgelöst wird. Ich höre auf diese Benachrichtigung in meiner Sicht Controller und untersuchen Sie die userInfo für Änderungen und Anzeigen von Daten entsprechend. Ich denke, dass du es normalerweise so machst, wenn du einen beständigen Ladenkoordinator mit zwei verbundenen MOCs hast. Aber ich bin mir nicht sicher, ob es der richtige Weg ist, wenn Sie Kind/Eltern-Kontexte haben.

Antwort

3

Ich würde sagen, dass NSManagedObjectContextObjectsDidChangeNotification Benachrichtigung ist wahrscheinlich nicht die beste Lösung.

Die Art, wie ich es mache und es funktioniert, folgt. Hier ist Haupt Kontext Schöpfung:

_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
_mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; 
_mainContext.persistentStoreCoordinator = _persistentStoreCoordinator; 

Hier Hintergrund Kontext Schöpfung:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
_backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; 
_backgroundContext.parentContext = self.mainContext; 

Nun Hintergrund Kontext ist nur zum Schreiben (oder Lesen) Objekte (im Hintergrund-Thread sein kann). Der Hauptkontext dient nur zum Lesen aus der Hauptwarteschlange. Speichern auf sollte Hintergrund Kontext wie folgt aussehen:

__block BOOL saved = [_backgroundContext save:error]; 
if (saved && _backgroundContext.parentContext) { 
    [_backgroundContext.parentContext performBlockAndWait:^{ 
     saved = [self.parentContext save:error]; 
    }]; 
} 

Diese Methode garantiert speichern, dass alle Änderungen werden zum Haupt Kontext vermehrt werden. Wenn Sie in vielen Hintergrundthreads viel Arbeit machen, werden Sie mit der Methode performBlockAndWait: besser vertraut, die einen gegenseitigen Ausschluss im Kontext bietet.

Wenn Sie über Änderungen an Objekten benachrichtigt werden möchten, müssen Sie nicht auf eine Benachrichtigung warten. Sie können einfach NSFetchedResultsController einrichten und sich als Delegierter registrieren.

3

Wenn der Haupt-MOC einen privaten Eltern-MOC für asynchrone I/O verwendet, ist das in Ordnung. Sie sollten diesen übergeordneten MOC jedoch nicht für andere Zwecke als für die Hintergrundverarbeitung im Auftrag des Haupt-MOC verwenden. Dafür gibt es viele Gründe (unter anderem Leistung und unangenehme Probleme im Zusammenhang mit transienten Objekt-IDs).

Wenn Sie Hintergrundaktualisierung des Geschäfts tun möchten, ist hier, was ich vorschlage.

PSC <--+-- PrivateMOC <---- MainMOC 
     | 
     +-- BackgroundPrivateMOC 

Dieser Hintergrund Betrieb ermöglichen, den die geringste Unterbrechung des Haupt MOC verursacht, während das PSC-Caches ermöglicht gemeinsam genutzt werden.

Jetzt, um Daten zu teilen ...

Das MainMOC sollte DidSave-Benachrichtigungen von BackgroundPrivateMO abhören und zusammenführen.

Der BackgroundMOC kann DidSave-Benachrichtigungen vom PrivateMOC abhören und zusammenführen.

Dies ermöglicht das Zusammenführen nur permanente Objekt-IDs zu verwenden und die Leistung zu optimieren.

+0

Ist es möglich, BGPrivateMOC als Kind von mainMOC zu erstellen und alle BG-Änderungen durch Speichern von BGPrivateMOC zu verbreiten? Ich habe es versucht, aber mein mainMOC hat keine Änderungen vom BGPrivateMOC erhalten. Entschied dich, deinen Stack auszuprobieren. Es wirkt wie ein Zauber. –

+0

Oh, etwas ist schief gelaufen, es funktioniert nicht mehr. Die Zusammenführung aktualisiert den Hauptkontext nicht. –

+0

Sie müssen mehr Details als das ... vielleicht geben Sie eine neue Frage mit Details über Ihr spezifisches Problem ... und vielleicht kommentieren Sie hier über diese Frage, wenn Sie wollen, dass ich es sehe ... –