2010-03-17 10 views
57

Tengo un NSManagedObjectContext en el que tengo una cantidad de subclases de NSManagedObjects, de modo que algunos son contenedores para otros. Lo que me gustaría hacer es mirar un objeto de nivel superior para recibir notificaciones de cualquier cambio en cualquiera de sus propiedades, asociaciones o propiedades/asociaciones de cualquiera de los objetos que contiene.¿Cómo puedo seguir/observar todos los cambios dentro de un subgrafo?

Usar el contexto 'hasChanges' no me da suficiente granularidad. El método de objetos 'actualizado' solo se aplica al objeto dado (y no a nada en sus asociaciones). ¿Existe una conveniente (quizás basada en KVO) en la que puedo observar los cambios en un contexto que se limitan a un subgráfico?

Respuesta

129

Querrá escuchar el NSManagedObjectContextObjectsDidChangeNotification para recoger todos los cambios en su modelo de datos. Esto se puede hacer utilizando un código como el siguiente:

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

que activará -handleDataModelChange: sobre cualquier cambio en el contexto myManagedObjectContext.

Su -handleModelDataChange: método podría ser algo como esto:

- (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 
} 

Como se puede ver, la notificación contiene información en la que gestionan los objetos se actualizan, borrar e insertar. A partir de esa información, debe poder actuar en respuesta a los cambios en su modelo de datos.

+0

Gracias! No estaba al tanto de esa notificación. Todavía parece una sobrecarga masiva tener que realizar una búsqueda cada vez que se envía la notificación. Dicho esto, no estoy seguro de cómo podría ser optimizado incluso por Apple; fundamentalmente, sigue siendo un cruce de gráficos. –

+4

Si usa un NSPredicate para filtrar a través de estos objetos, en realidad es bastante efectivo porque todo está en la memoria. Utilizo esta solución en varias aplicaciones para el iPhone y todavía no se ha producido un cuello de botella de rendimiento en esta área. –

+0

Ah, es una buena idea usar un NSPredicate. No había pensado en eso. –

19

aquí es un ejemplo sencillo en 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

Normalmente se necesita realizar un seguimiento del valor de retorno 'let observation = NSNotificationCenter.defaultCenter(). AddObserverForName (..) {..}' para poder dejar de observar llamando a 'NSNotificationCenter.defaultCenter(). RemoveObserver (observación) '. –

+1

@ DanBeaulieu, si usó la versión bloqueada, 'NSNotificationCenter.defaultCenter(). AddObserverForName (..) {..}', necesita mantener la observación devuelta. –

+0

@LevLandau Voy a deshacer mi edición y leer, gracias por informar –

0

para mí es sólo perdió dos siguientes func, tal vez esto ahorrará horas para alguien

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

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

Esto no tiene nada que ver con la pregunta. – rmaddy

Cuestiones relacionadas