ios core-data nsfetchedresultscontroller ios10

Core Data iOS10: viewContext no recibe actualizaciones de newBackgroundContext() con NSFetchResultController



core-data nsfetchedresultscontroller (4)

En mi aplicación, tengo un NSFetchResultController para cargar objetos de Datos Core en un UITableView. La solicitud de recuperación asociada con este FRC usa la nueva propiedad viewContext disponible para NSPersistentContainer (iOS10).

Cuando selecciono una celda, paso el objeto Core Data a un nuevo ViewController. Este nuevo VC todavía usa el viewContext. Desde este ViewController, puedo actualizar el objeto Core Data desde los ViewControllers presentados de manera modal. Para hacerlo, uso newBackgroundContext() para los ViewControllers modales. Puedo guardar la actualización del objeto Core Data sin ningún problema.

El problema es que el FRC no se actualiza automáticamente con la actualización del objeto Core Data desde el contexto de fondo. Es como si viewContext no recibiera ni manejara las actualizaciones de objetos de Core Data.

Si configuro automaticallyMergesChangesFromParent en true para viewContext (en toda la aplicación), el FRC obtiene el objeto Core Data actualizado cuando guardo el contexto de fondo. A mi entender, viewContext debe administrar la combinación de datos automáticamente. La documentación describe el viewContext con: "Este contexto está configurado para ser generacional y para consumir automáticamente las notificaciones de guardado de otros contextos".

¿Puede aclarar cómo manejar los diferentes contextos con un NSFetchResultController?

Gracias axel


Estás viendo el comportamiento correcto. Si desea que su viewContext capte automáticamente los cambios de otros contextos, incluidos los creados por newBackgroundContext() , debe establecer automaticallyMergesChangesFromParent newBackgroundContext() en true .

Estoy de acuerdo en que los documentos son confusos en ese punto, "... y consumir automáticamente guardar notificaciones de otros contextos".


Fusionar automáticamente los cambios de las necesidades primarias para establecer en viewContext de esta manera:

persistentContainer.viewContext.automaticallyMergesChangesFromParent = true


No funcionó para mí, así que cambié guardar bloque de

self.persistentContainer.performBackgroundTask { (context) ... }

a

self.persistentContainer.newBackgroundContext().performAndWait { ... }

y de la configuración de corse true automaticallyMergesChangesFromParent para hacer que la fusión automática funcione.

lazy var viewContext: NSManagedObjectContext = { self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true self.presistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump return self.persistentContainer.viewContext }()

No sé por qué el context de performBackgroundTask no se fusionó con viewContext .


No me he encontrado con esto directamente, pero su problema me parece extraño si el newBackgroundContext de hecho estuviera en capas bajo el viewContext ya que cualquier guardado del nuevo contexto solo actualizaría el viewContext, que también tendría que hacer su propio guardado para obtener los cambios en el almacén persistente (que usted dice que están ocurriendo correctamente). Basándome en esa sospecha, miré los documentos del desarrollador donde Apple dice:

Invocar este método (newBackgroundContext ()) hace que el contenedor persistente cree y devuelva un nuevo NSManagedObjectContext con el concurrencyType establecido en privateQueueConcurrencyType. Este nuevo contexto se asociará directamente con el NSPersistentStoreCoordinator y está configurado para consumir las difusiones de NSManagedObjectContextDidSave automáticamente.

Por lo tanto, no estaría en una relación padre-hijo con el viewContext. Según la guía, parece que el nuevo contexto sería notificado de los cambios por el antiguo, pero no al revés, por lo que tendría que hacer una actualización en el viewContext cuando cambie el nuevo contexto, lo que podría hacer mediante programación si puede rastree eso en su código o quizás use una de las notificaciones de cambio en NSManagedObjectsContext para desencadenar la acción.