CoreData y security de subprocesss

Tengo un nombre CoreDataManager que registra mergeContextChangesForNotification en él:

 + (id) shanetworkingManager{ static CoreDataManager *mShanetworkingManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ mShanetworkingManager = [[CoreDataManager alloc] init]; }); return mShanetworkingManager; } - (id)init { self = [super init]; if (self) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:nil]; }); } return self; } 

Después de recibir la notificación:

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { [shareContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES]; } 

Tengo dos preguntas aquí:

  1. ¿Debo usar performSelectorOnMainThread aquí? ya que esta respuesta dice nunca. ¿Debo cambiarlo a GCD y usar dispatch_get_main_queue ??
  2. ¿El logging de mergeContextChangesForNotification en init es una buena práctica para garantizar que la notificación siempre se registre en el hilo principal? que leo de esta respuesta

Con los types de concurrency de object gestionado introducidos en iOS 5 / OS X 10.7, se prefiere usar los methods performBlock para garantizar que se ejecute una operación Core Data en el hilo correcto (más precisamente: en la queue derecha).

Entonces crearías el context compartido con

 shareContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 

y combinar cambios de otros contexts con

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { [shareContext performBlock:^{ [shareContext mergeChangesFromContextDidSaveNotification:notification]; }]; } 

Tenga en count también que (como se indica en la documentation NSManagedObjectContext ), se recomienda registrarse para save notifications solo de contexts conocidos. Con object:nil en su logging puede recibir notifications inesperadas porque los frameworks del sistema usan Core Data internamente.

Por lo tanto, debe registrarse solo para los contexts que cree. Alternativamente, puede verificar que se envió una notificación desde un context con el mismo coordinador de tienda persistente:

 - (void)mergeContextChangesForNotification:(NSNotification *)notification { NSManagedObjectContext *otherContext = [notification object]; if (otherContext != shareContext && [otherContext persistentStoreCoordinator] == [shareContext persistentStoreCoordinator]) { [shareContext performBlock:^{ [shareContext mergeChangesFromContextDidSaveNotification:notification]; }]; } } 

Finalmente, siempre se llama a un método de notificación en el hilo en el que se publicó . No importa en qué hilo se registre la notificación. Por lo tanto, no es necesario enviar el logging al hilo principal.

Compruebe la aplicación de muestra TopSongs , tenga en count que no son perfectos, pero la mayoría de las veces puede utilizarse como reference. Están sincronizando mergeChangesFromContextDidSaveNotification llamadas mergeChangesFromContextDidSaveNotification para que se realicen solo en el hilo principal, pero hacerlo de una manera un poco más elegante:

 // This method will be called on a secondary thread. Forward to the main thread for safe handling of UIKit objects. - (void)importerDidSave:(NSNotification *)saveNotification { if ([NSThread isMainThread]) { [self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification]; [self.songsViewController fetch]; } else { [self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO]; } } 

En cuanto a la initialization, se -init en el mismo hilo +shanetworkingManager .

Además, dado que la segunda respuesta vinculada no es muy informativa en términos de documentation, déjeme dejar un enlace a la sección Concurrencia con datos básicos de los documentos.