2010-03-17 16 views
57

Ich habe einen NSManagedObjectContext, in dem ich eine Reihe von Unterklassen von NSManagedObjects habe, so dass einige Container für andere sind. Ich möchte beobachten, wie ein Objekt auf oberster Ebene über Änderungen an seinen Eigenschaften, Assoziationen oder den Eigenschaften/Assoziationen der darin enthaltenen Objekte benachrichtigt wird.Wie kann ich alle Änderungen innerhalb eines Untergraphen verfolgen/beobachten?

Die Verwendung der 'hasChanges' des Kontexts gibt mir nicht genug Granularität. Die Methode 'isUpdated' der Objekte gilt nur für das angegebene Objekt (und nichts in seinen Zuordnungen). Gibt es eine bequeme (vielleicht KVO-basierte) war ich Änderungen in einem Kontext, die auf einen Teilgraphen beschränkt sind?

Antwort

129

Sie sollten auf die NSManagedObjectContextObjectsDidChangeNotification achten, um alle Änderungen an Ihrem Datenmodell abzurufen. Dies kann unter Verwendung von Code wie folgt erfolgen:

[[NSNotificationCenter defaultCenter] 
     addObserver:self 
     selector:@selector(handleDataModelChange:) 
      name:NSManagedObjectContextObjectsDidChangeNotification 
      object:myManagedObjectContext]; 

die -handleDataModelChange: auf alle Änderungen des myManagedObjectContext Kontext auslösen.

Ihre -handleModelDataChange: Methode würde wie folgt aussehen:

- (void)handleDataModelChange:(NSNotification *)note 
{ 
    NSSet *updatedObjects = [[note userInfo] objectForKey:NSUpdatedObjectsKey]; 
    NSSet *deletedObjects = [[note userInfo] objectForKey:NSDeletedObjectsKey]; 
    NSSet *insertedObjects = [[note userInfo] objectForKey:NSInsertedObjectsKey]; 

    // Do something in response to this 
} 

Wie Sie sehen können, die Benachrichtigung Informationen, auf die verwalteten Objekte wurden aktualisiert, gelöscht und eingefügt enthält. Anhand dieser Informationen sollten Sie in der Lage sein, auf Änderungen Ihres Datenmodells zu reagieren.

+0

Dank! Ich war mir dieser Benachrichtigung nicht bewusst. Es scheint immer noch wie ein massiver Overkill zu sein, eine Suche jedes Mal durchzuführen, wenn die Benachrichtigung gesendet wird. Das heißt, ich bin mir nicht sicher, wie es auch von Apple optimiert werden könnte; Grundsätzlich ist es immer noch ein Graph Traversal. –

+4

Wenn Sie ein NSPredicate verwenden, um durch diese Objekte zu filtern, ist es tatsächlich ziemlich performant, weil alles im Speicher ist. Ich verwende diese Lösung in mehreren Anwendungen für das iPhone und es gibt in diesem Bereich noch keinen Leistungsengpass. –

+0

Ah, guten Ruf mit einem NSPredate. Hatte nicht daran gedacht. –

19

hier ist ein einfaches Beispiel in Swift:

NotificationCenter.default.addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: nil, queue: nil) { note in 
     if let updated = note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>, updated.count > 0 { 
      print("updated: \(updated)") 
     } 

     if let deleted = note.userInfo?[NSDeletedObjectsKey] as? Set<NSManagedObject>, deleted.count > 0 { 
      print("deleted: \(deleted)") 
     } 

     if let inserted = note.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject>, inserted.count > 0 { 
      print("inserted: \(inserted)") 
     } 
    } 
+3

Normalerweise muss man den Rückgabewert verfolgen 'lassen Sie observation = NSNotificationCenter.defaultCenter(). AddObserverForName (..) {..}' um die Beobachtung durch Aufruf von 'NSNotificationCenter.defaultCenter() zu beenden. RemoveObserver (observation) '. –

+1

@DanBeaulieu, wenn Sie die blockbasierte Version 'NSNotificationCenter.defaultCenter(). AddObserverForName (..) {..}' verwendet haben, müssen Sie die zurückgegebene Beobachtung behalten. –

+0

@LevLandau Ich werde meine Bearbeitung rückgängig machen und lesen, danke für die Information –

0

für mich folgende zwei func gerade verloren hat, das vielleicht Stunden für

jemand speichern
func controllerWillChangeContent(controller: NSFetchedResultsController) { 
    tableView.beginUpdates() 
} 

func controllerDidChangeContent(controller: NSFetchedResultsController) { 
    tableView.endUpdates() 
} 
+2

Das hat nichts mit der Frage zu tun. – rmaddy

Verwandte Themen