ios objective-c core-data nsmanagedobjectcontext magicalrecord

ios - EXC_BAD_ACCESS en mergeChangesFromContextDidSaveNotification



objective-c core-data (3)

Hemos estado tratando de depurar un problema de subprocesos / subprocesos de Datos principales en el que la fusión de una notificación de guardado de Datos principales en nuestro hilo principal NSManagedObjectContext está fallando esporádicamente la aplicación. Esto se está estrellando ~ 2% de nuestras sesiones de aplicaciones y no sabemos cómo resolver esto. Realmente agradeceríamos cualquier orientación o consejo general sobre qué podría causar este choque.

Tenemos una configuración de Core Data que se ve así:

NB Esta es la pila de Datos Core predeterminada en Magical Record v2.3 creada desde [MagicalRecord setupAutoMigratingCoreDataStack]

Este es el escenario donde nuestra aplicación está fallando:

  1. La solicitud HTTP devuelve JSON
  2. JSON se analiza en NSManagedObject s (algunas entidades nuevas, algunas entidades actualizadas) en el contexto de ahorro de raíz
  3. El contexto de ahorro de raíz se guarda en un almacén persistente
  4. NSManagedObjectContextDidSaveNotification es transmitido por Core Data. El contexto predeterminado en la cola principal observa esto y llama a mergeChangesFromContextDidSaveNotification: con el NSDictionary de cambios en el hilo principal.
  5. Se bloquea cuando se envía objectID a un objeto no válido (lo más probable es que NSManagedObject haya sido desasignado).

Esto está ocurriendo dentro de la implementación privada de NSManagedObjectContext mergeChangesFromContextDidSaveNotification: por lo que es imposible para nosotros ver qué es lo que realmente salió mal aquí; todo lo que podemos decir en este punto que un objeto que debería existir, no existe.

Esto solo sucede en un pequeño porcentaje de los datos guardados de Core Data, lo que indica que puede no ser un defecto fundamental en nuestra pila Core Data → API. Además, no hay ninguna indicación de que el tamaño o el tipo de los cambios (inserciones / actualizaciones / eliminaciones) en los cambios de contexto tengan algún impacto en la probabilidad de la falla.


Ha pasado un tiempo desde que esta pregunta se publicó y, después de redescubrirla, me gustaría responder a mi propia pregunta por el bien de otros que encuentran este hilo.

En mi caso, había migrado una base de código grande de mi hermano NSManagedObjectContexts actualizado a través de NSManagedObjectContextDidSaveNotification . Sin embargo, el problema realmente no tenía nada que ver con esto, a pesar de que esto expuso el problema.

La causa real de esto fue que había partes más antiguas del código, configuradas por ingenieros anteriores, que habían configurado KVO en NSManagedObject y sus propiedades. Se supo que KVO en las entidades Core Data es, de hecho, una muy mala idea.

Más exactamente, pareció que esto sucedió cuando KVO se configuró en entidades y el objeto, o el objetivo de una relación en este objeto se eliminó del NSPersistentStore . Esta segunda condición no parece ser la única causa del problema, pero definitivamente fue una causa muy importante en mi situación.

Lecciones aprendidas:

  1. Use un controlador de resultados cuando lo necesite. KVO no es un método abreviado conveniente y no debe evitar migrar el código KVO Core Data KS a NSFetchedResultsControllers u otra alternativa sensata, ya que la postergación lo perjudicará.
  2. Los datos principales de subprocesos múltiples son una habilidad difícil pero muy valiosa para convertirse en un experto. Conocer su pila de datos básicos y los matices y limitaciones de los subprocesos múltiples de datos básicos es absolutamente valioso para toda la angustia mental.

La documentación de NSManagedObjectContextDidSaveNotification dice que:

"Puede pasar el objeto de notificación a mergeChangesFromContextDidSaveNotification: en otro hilo, sin embargo, no debe usar el objeto administrado en el diccionario de información del usuario directamente en otro hilo. Para obtener más información, consulte Simultaneidad con los datos básicos en la Guía de programación de datos básicos".

Tal vez este es el problema? Me aseguraría de que el objeto que obtienes de la notificación se guarde en el Contexto predeterminado en el mismo hilo que Root publicó.


Una posibilidad es que su tienda persistente se haya corrompido y se encuentre en un estado inconsistente. Si esto sucede, se genera un código de error con el que el Registro Mágico no se ocupa necesariamente. Esto puede ser el origen de una serie de fallos aparentemente aleatorios difíciles de repetir relacionados con el Registro Mágico (y pueden o no considerarse un error del Registro Mágico).

Vale la pena leer los subprocesos de problemas del Registro Mágico here (el mismo problema) y here (problema diferente, pero podría ser una causa similar). Cuando llegué a estos problemas, logré hacer algunas correcciones de parches temporales siguiendo varias sugerencias en esos hilos, pero al final decidí eliminar mi dependencia de Magical Record, y desde entonces no he tenido problemas.