Excepción / locking al fusionar contexts administrados CoreData

Obtengo la siguiente exception cuando bash combinar un context administrado (que se ejecuta en un hilo de background) con mi context administrado principal (en mainthread). No puedo ver la exception en mi propia expresión @try. ¿Alguien tiene alguna idea de este problema?

Estoy usando la política de combinación pnetworkingeterminada, pero no estoy seguro de que sea correcta, este problema es muy intermitente, sucede rara vez, pero hace que mi aplicación se bloquee.

Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x00000000, 0x00000000 Crashed Thread: 0 Last Exception Backtrace: 0 CoreFoundation 0x37e3b8bf __exceptionPreprocess + 163 1 libobjc.A.dylib 0x319211e5 objc_exception_throw + 33 2 CoreData 0x344b7ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1 3 CoreData 0x344b774f -[NSSQLiteConnection prepareSQLStatement:] + 55 4 CoreData 0x3455b049 -[NSSQLChannel selectRowsWithCachedStatement:] + 61 5 CoreData 0x34586d63 newFetchedRowsForFetchPlan_MT + 783 6 CoreData 0x344bfb07 -[NSSQLCore newRowsForFetchPlan:] + 351 7 CoreData 0x34565011 -[NSSQLCore fetchRowForObjectID:] + 1005 8 CoreData 0x344d1a57 -[NSSQLCore newValuesForObjectWithID:withContext:error:] + 195 9 CoreData 0x344d0f83 _PFFaultHandlerLookupRow + 423 10 CoreData 0x3450e111 -[NSFaultHandler fulfillFault:withContext:] + 25 11 CoreData 0x34518999 -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:] + 77 12 CoreData 0x345178ef -[NSManagedObject(_NSInternalMethods) _newAllPropertiesWithRelationshipFaultsIntact__] + 79 13 CoreData 0x345284db -[NSManagedObjectContext(_NSInternalChangeProcessing) _establishEventSnapshotsForObject:] + 47 14 CoreData 0x3452694b -[NSManagedObjectContext deleteObject:] + 155 15 CoreData 0x345238a1 -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 813 16 CoreData 0x34522c35 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 189 17 myapp 0x0008f0e9 0x8d000 + 8425 18 CoreFoundation 0x37d9a22b -[NSObject performSelector:withObject:] + 43 19 Foundation 0x31d75757 __NSThreadPerformPerform + 351 20 CoreFoundation 0x37e0fb03 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 21 CoreFoundation 0x37e0f2cf __CFRunLoopDoSources0 + 215 22 CoreFoundation 0x37e0e075 __CFRunLoopRun + 653 23 CoreFoundation 0x37d914dd CFRunLoopRunSpecific + 301 24 CoreFoundation 0x37d913a5 CFRunLoopRunInMode + 105 25 GraphicsServices 0x3790ffcd GSEventRunModal + 157 26 UIKit 0x35221743 UIApplicationMain + 1091 

Inicío el context de background en start () de un nsoperation así:

 AppDelegate *appController = [[UIApplication shanetworkingApplication] delegate]; _managedObjectContext = [[NSManagedObjectContext alloc] init]; [appController setPersistentStore:_managedObjectContext]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedDeletedObjects:) name:NSManagedObjectContextDidSaveNotification object:_managedObjectContext]; 

También configuré un evento de notificación que se llama cuando se borran los objects en el context administrado en segundo plano, la callback luego:

 -(void)receivedDeletedObjects:(NSNotification *)note { AppDelegate *appController = [[UIApplication shanetworkingApplication] delegate]; NSManagedObjectContext *mainContext = [self managedObjectContext]; [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:note waitUntilDone:NO]; } 

Eso es más o less el código. Tengo 4 hilos de background diferentes, cada uno con su propio context gestionado haciendo lo mismo fusionándose con el context principal de esta manera. Me pregunto si varios hilos entrarán en mergeChangesFromContextDidSaveNotification al mismo time, pero este no debería ser el caso, ya que siempre se llama en el hilo principal.

Qué tal esto:

(todo en AppDelegate, invoca freshContextForBackgroundTask desde un background Thread y usa save: para activar la combinación). Note syncObj es una instancia sencilla de NSObject necesaria para la synchronization dentro del delegado de la aplicación cuando usa muchos subprocesss de background (o simplemente tiene mala suerte con la progtwigción)

 -(NSManagedObjectContext*) freshContextForBackgroundTask { @synchronized(syncObj) { NSManagedObjectContext* r = [[NSManagedObjectContext alloc] init]; [r setPersistentStoreCoordinator:self.managedObjectContext.persistentStoreCoordinator]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:r]; return r; } } - (void)backgroundContextDidSave:(NSNotification *)notification { /* Make sure we're on the main thread when updating the main context */ //NSLog(@"merging change: %@",notification); dispatch_async(dispatch_get_main_queue(), ^{ NSManagedObjectContext *context = [self managedObjectContext]; // this for loop may not be needed for your purpose. for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) { [[context objectWithID:[object objectID]] willAccessValueForKey:nil]; } [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; }); } 

Su enfoque parece extraño. Especialmente cuando configuras la tienda persistente del delegado de la aplicación en el (cero) uno del context recién iniciado.