2011-01-27 29 views
8

Estoy escribiendo una aplicación para iPad que muestra artículos y descargas nuevos artículos en un NSOperation separada en una cola y los inserta en la fusión de datos básicos. Actualmente tengo un contexto separado para la operación, creado en el método principal de la operación y usando el mismo coordinador que el contexto principal. Yo uso el mismo patrón que se ha sugerido un montón de escuchar en esa operación para NSManagedObjectContextDidSaveNotification y luego llamar mergeChangesFromContextDidSaveNotification en el contexto del hilo principal. El problema es que estoy recibiendo este error:fondo de Datos Básicos de hilo NSManagedObjectContext error

2011-01-27 07:26:02.574 Zagazine[12298:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x3284b987 __exceptionPreprocess + 114 
    1 libobjc.A.dylib      0x31aca49d objc_exception_throw + 24 
    2 CoreData       0x3549d07b _PFRetainedObjectIDCore + 638 
    3 CoreData       0x3549cdfb - [NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:] + 14 
    4 CoreData       0x354bf85b -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 2170 
    5 CoreFoundation      0x327e9bbf -[NSObject(NSObject) performSelector:withObject:] + 22 
    6 Foundation       0x320fd795 __NSThreadPerformPerform + 268 
    7 CoreFoundation      0x328017dd __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12 
    8 CoreFoundation      0x327d34fb __CFRunLoopDoSources0 + 194 
    9 CoreFoundation      0x327d2e5b __CFRunLoopRun + 230 
    10 CoreFoundation      0x327d2c87 CFRunLoopRunSpecific + 230 
    11 CoreFoundation      0x327d2b8f CFRunLoopRunInMode + 58 
    12 GraphicsServices     0x3094a4ab GSEventRunModal + 114 
    13 GraphicsServices     0x3094a557 GSEventRun + 62 
    14 UIKit        0x32c14329 -[UIApplication _run] + 412 
    15 UIKit        0x32c11e93 UIApplicationMain + 670 
    16 ArticleApp       0x0000233f main + 70 
    17 ArticleApp       0x000022f4 start + 40 
) 
terminate called after throwing an instance of 'NSException' 
Program received signal: “SIGABRT”. 

Esta parte interesante es que este error sólo se produce la primera vez que inicie la aplicación después de instalarla. Todos los lanzamientos posteriores después de su instalación funcionan bien. ¿Alguien sabe por qué ocurre este error y por qué solo ocurrirá en la instalación inicial?

Además, esta es la forma en que estoy fusionando el contexto, esto se llama el subproceso en segundo plano cuando se reciba la notificación:

- (void)mergeChanges:(NSNotification *)notification { 
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; 
    NSManagedObjectContext *mainContext = [appDelegate managedObjectContext]; 

    // Merge changes into the main context on the main thread 
    [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
           withObject:notification 
          waitUntilDone:YES]; 
} 

Respuesta

17

This interesting part is that this error only occurs the first time I launch the app after installing it. All subsequent launches after it's installed work fine. Does anyone know why this error is happening and why it would only happen on initial install.

Mi conjetura es entonces que el almacén persistente no está correctamente asociado a el archivo en el disco correctamente en el primer lanzamiento. El archivo que respalda el almacén de datos centrales no se materializa cuando asigna su URL al coordinador de tienda persistente. Solo se materializa cuando se guarda por primera vez.

y la fusión de los cambios sin tener un archivo de copia listo provoca una gran cantidad de problemas.

intente guardar el contexto de una vez desde el hilo principal en la primera puesta en marcha muy temprano en la ejecución, cuando el contexto de Datos Básicos todavía está vacío, antes de crear el subproceso en segundo plano. Espero que eso resuelva tu problema.

+0

Sí que funciona, he añadido el código para eliminar todos los objetos en el lanzamiento de aplicaciones antes de cualquier otro fondo acaecer cosas y lo hizo el truco. ¿Es esto normal? ¿Hay algo mal con mi diseño? Actualmente tengo que iniciar una cola de operación de sincronización en la aplicación: didFinishLaunchingWithOptions que descarga datos e inserciones. – marchinram

+1

No tiene que eliminar los objetos al guardar. Cuando dije que deberías guardar una vez cuando el contexto de Core Data está vacío, solo quise decir que debes guardar desde el principio, cuando el programa se inicia por primera vez después de instalarlo en un dispositivo determinado. Tu diseño está perfectamente bien para mí. Es solo que acceder a los datos centrales desde un hilo de fondo es ... ¡complicado! – Yuji

+0

Borro los objetos puramente para probarlos, descargo json de un servicio web y lo inserto en mi tienda, por lo que me gusta cambiar los datos json para probarlo. Perdón por la confusión y gracias por su respuesta. +1 – marchinram

0

¿Ha tenido ninguna otra notificación mergeChangesFromContextDidSaveNotification ser observado por cualquier otro contexto? Si es así, podría ser el orden que estás notificando. Podría estar notificando a un contexto que no sabe sobre el esquema al que están afectando los cambios (también conocido como 'El almacén persistente del objeto no es accesible desde este coordinador de NSManagedObjectContext').

Cuestiones relacionadas