2010-12-17 9 views
7

alt textAyuda con Core multiproceso de diseño de aplicaciones de datos

Por encima es una simplificación de lo que mi modelo se parece. Mi aplicación tiene un objeto NSWindowController que controla dos objetos NSViewController para las usuario y entidades de la cuenta. Cuando un usuario inicia sesión en la aplicación, puede modificar la información del usuario o de la cuenta al mostrar el controlador de vista relevante. En el fondo, la aplicación completa periódicamente los registros del usuario en el delegado de la aplicación en un hilo separado.

Estoy usando un NSManagedObjectContext separado para el hilo de fondo y el NSManagedObjectContext del delegado de la aplicación para la entrada de datos en los controladores de vista. Me gustaría saber algunas cosas:

1) ¿Es esta una buena práctica? ¿Debo crear un NSManagedObjectContext para cada controlador de vista y luego combinar los contextos cada vez que el usuario termine de hacer cambios?

2) Como la entidad de registro se crea en el hilo de fondo, tiene su propio NSManagedObjectContext. Sin embargo, cada registro incluye información de las usuario y entidades de cuenta, que se crean en el delegado de la aplicación NSManagedObjectContext. Esta es la forma en que estoy Recogida de una de usuario:

- (NSManagedObjectID*) fetchUser:(NSString*) userID { 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"user":inManagedObjectContext:self.managedObjectContext]; 
    /** snip **/ 
} 

Este método es llamado por el subproceso de fondo de la siguiente manera:

NSManagedObjectID* userObjectID = [self fetchUser:userID]; 
NSManagedObject* userObject = [self.logsManagedObjectContext objectWithID:userObjectID]; 

Es lo que estoy haciendo en fetchUser flujos seguros? ¿Debo bloquear el contexto principal del objeto gestionado mientras busco un usuario en caso de que una de las vistas esté modificando al mismo usuario? De this article entiendo (quizás incorrectamente) que tal vez tenga que hacerlo. Hasta ahora no he tenido ningún problema, pero no quiero dejar un posible caso marginal.

3) Cuando uno de los controladores de vista hace cambios a la NSManagedObjectContext se publica una notificación que se maneja de la siguiente manera el delegado aplicación:

- (void)contextDidSave:(NSNotification *)notification { 
    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
    [self.logManagedObectContext performSelector:selector onThread:backgroundThread withObject:notification waitUntilDone:NO]; 
} 

¿Es así como debería manejar la fusión o debería ser la fusión de la delegado de la aplicación NSManagedObjectContext en su lugar? Descubrí que al hacer eso (en el hilo principal) cerraba la UI.

Cualquier ayuda será apreciada.

Respuesta

9

NSManagedObjectContext objetos no son seguros para subprocesos. Esto significa que si desea acceder a los datos centrales desde múltiples hilos, necesitará uno para cada hilo (y también se creará en el hilo). Cada uno de estos puede usar el mismo NSPersistentStoreCoordinator, que serializará el acceso al almacén persistente.

Esto ocurre debido a que cada NSManagedObjectContextsabe cómo bloquear adecuadamente el NSPersistentStoreCoordinator cuando está en uso, evitando colisiones. Al seguir estas reglas, debes permanecer seguro de subprocesos.

Como ya lo está haciendo, los objetos NSManagedObjectID se deben usar para pasar objetos de datos centrales de un MOC a otro (y por extensión de un hilo a otro).Sin embargo, está llamando al fetchUser:, que usa el MOC de su hilo principal, en el fondo. Esto no es correcto Esa llamada al método fetchUser: debe invocarse desde el hilo principal. Por supuesto, no hay nada que le impida recuperar el usuario en el hilo de fondo usando el MOC de fondo.

En resumen, siempre hacen llamadas a un NSManagedObjectContext del hilo que fue creado en.

El truco aquí es asegurarse de que ambos MOC saben acerca de la otra de guarda, por lo que debe registrarse para recibir las notificaciones de cada contexto. Debería entonces realizar el mergeChangesFromContextDidSaveNotification: desde el hilo apropiado para el MOC. Por el momento, su contexto de fondo está siendo notificado sobre los cambios del contexto del hilo principal, pero no al revés.

Ah, y no hay necesidad de tener un contexto separado para cada NSViewController. Como elementos de IU, sus interacciones con el contexto ocurrirán en el mismo hilo (principal), por lo que compartir está bien.

+0

No sabía que podía recuperar al usuario desde el fondo MOC. Todo lo que tengo que hacer es darles el mismo ** NSPersistentStoreCoordinator **? Si lo hago, ¿necesito recuperar usando Object ID o puedo obtener el objeto directamente? – David

+0

Puede obtener los objetos directamente. Solo asegúrese de escribir el código para fusionar los cambios a la notificación de cualquier otro MOC que comparta el mismo coordinador. – paulbailey

Cuestiones relacionadas