Uso de datos básicos de forma concurrente y confiable

Estoy creando mi primera aplicación de iOS, que en teoría debería ser bastante sencilla, pero tengo dificultades para que sea lo suficientemente a prueba de balas para que me sienta confiado al enviarla a la App Store.

Brevemente, la pantalla principal tiene una vista de tabla, al seleccionar una fila, se va a otra vista de tabla que muestra información relevante para la fila seleccionada en una forma de detalle maestro. Los datos subyacentes se recuperan como datos JSON de un servicio web una vez al día y luego se almacenan en caché en un almacén de Core Data. Los datos anteriores a ese día se eliminan para evitar que el archivo de base de datos SQLite crezca indefinidamente. Todas las operaciones de persistencia de datos se realizan utilizando Core Data, con unNSFetchedResultsController apuntalando la vista detallada de la tabla.

El problema que estoy viendo es que si cambia rápidamente entre las pantallas maestra y de detalle varias veces mientras se recuperan, analizan y guardan los datos nuevos, la aplicación se congela o se bloquea por completo. Parece que hay algún tipo de condición de carrera, tal vez debido a que los Datos del Core importan datos en segundo plano mientras el hilo principal intenta realizar una búsqueda, pero estoy especulando. He tenido problemas para capturar cualquier información de bloqueo significativa, por lo general es un SIGSEGV en lo profundo de la pila de Datos Core.

La siguiente tabla muestra el orden real de los eventos que suceden cuando se carga el controlador de vista de tabla de detalles:

Main Thread                          Background Thread
viewDidLoad

                                     Get JSON data (using AFNetworking)

Create child NSManagedObjectContext (MOC)

                                     Parse JSON data
                                     Insert managed objects in child MOC
                                     Save child MOC
                                     Post import completion notification

Receive import completion notification
Save parent MOC
Perform fetch and reload table view

                                     Delete old managed objects in child MOC
                                     Save child MOC
                                     Post deletion completion notification

Receive deletion completion notification
Save parent MOC

Una vez que el bloque de finalización de AFNetworking se activa cuando llegan los datos JSON, se anida unNSManagedObjectContext se crea y se pasa a un objeto "importador" que analiza los datos JSON y guarda los objetos en el almacén de Core Data. El importador ejecuta utilizando el nuevoperformBlock Método introducido en iOS 5:

NSManagedObjectContext *child = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [child setParentContext:self.managedObjectContext];        
    [child performBlock:^{
        // Create importer instance, passing it the child MOC...
    }];

El objeto importador observa sus propios MOC's.NSManagedObjectContextDidSaveNotification y luego publica su propia notificación que es observada por el controlador de vista de tabla de detalles. Cuando se publica esta notificación, el controlador de vista de tabla realiza un guardado en su propio MOC (principal).

Utilizo el mismo patrón básico con un objeto "deleter" para eliminar los datos antiguos después de que se hayan importado los nuevos datos del día. Esto ocurre de forma asincrónica después de que el controlador de resultados recuperado haya recuperado los nuevos datos y se haya vuelto a cargar la vista de la tabla detallada.

Una cosa que no estoy haciendo es observar las notificaciones de combinación o bloquear cualquiera de los contextos de objeto administrado o el coordinador de tienda persistente. ¿Es esto algo que debería estar haciendo? No estoy seguro de cómo diseñar todo esto correctamente, así que agradecería cualquier consejo.

Respuestas a la pregunta(4)

Su respuesta a la pregunta