2012-04-03 12 views
11

Según la respuesta de Daniel Eggert en this question, cuando se utiliza un marco de objeto gestionado con NSPrivateQueueConcurrencyType es necesario hacer nada que lo toca o los objetos que pertenecen a la misma dentro de performBlock: o performBlockAndWait:¿Es necesario realizar lecturas de datos centrales dentro de performBlock cuando se usa NSMainQueueConcurrencyType?

Es la misma verdad para NSMainQueueConcurrencyType? Imagine el siguiente código que se ejecuta en el hilo principal, en un UIViewController por ejemplo:

self.moc = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease]; 
//moc setup 

__block RHWidget *widget = nil; 

[self.moc performBlockAndWait:^{ 
    widget = [(RHWidget *)[self.moc objectWithID:self.widgetObjectID] retain]; 
}]; 

self.labelView.text = widget.descriptionString; 

[widget release]; 

¿Es seguro utilizar el widget fuera del bloque, ya que sabemos que estamos en el hilo principal? O es necesario hacer esto:

__block NSString *description = nil; 

[self.moc performBlockAndWait:^{ 
    RHWidget *widget = (RHWidget *)[self.moc objectWithID:self.widgetObjectID]; 
    description = [widget.descriptionString copy]; 
}]; 

self.labelView.text = description; 

[description release]; 

hacer cosas cambian si hay otro NSManagedObjectContext por ahí, posiblemente del tipo cola privada, haciendo el trabajo en bloques y empujando cambios hasta self.moc como parentContext?

Este es un ejemplo ligeramente artificial, por supuesto, pero sería bueno pasar con seguridad ese widget a, por ejemplo, un controlador de vista modal que necesita acceder a algunas de las propiedades del widget. ¿Debo pasar el objectID del widget en su lugar y volver a registrarlo dentro del performBlock: en el nuevo controlador de vista?

+0

Hay un artículo muy completo [aquí] (http://www.cocoanetics.com/2012/07/multi-context-coredata/) que describe los diversos enfoques, incluidos los tipos de concurrencia de contexto y los contextos anidados. –

Respuesta

6

Actualización: Según WWDC 2011 Session 303 (What's New in Core Data on iOS), NSMainQueueConcurrencyType está destinado a permitir la mensajería normal en el hilo principal; solo necesita usar -performBlock: al interactuar con el contexto de un hilo diferente. (partes Naturaleza pertinentes de mi respuesta original a continuación.)


He hecho una aplicación o dos que modifica la plantilla por defecto "Maestro-Detalle" de la aplicación de Xcode para hacer que el "principal" MOC (creados por la aplicación delegar y pasar entre los controladores de vista) main-queue-only, y parent a un contexto de cola privada que utilizo para operaciones en segundo plano, como la importación de datos desde una búsqueda web. Por lo tanto, la mayoría de los usos del contexto y sus objetos ocurren sin estar incluidos en performBlock:. (La única vez que utilizo performBlock: es llevar los cambios desde el contexto de la tarea en segundo plano al principal para actualizar la UI). Funciona bien.

+0

Eso es más o menos lo que estoy haciendo; Tengo un singleton con 'NSOperationQueue' y un contexto con' NSPrivateQueueConcurrencyType' que se pasa a cada operación. Esas operaciones captan objetos, hacen su trabajo, guardan el contexto local y luego guardan el contexto principal, todo dentro de 'performBlock:'. Todo parece funcionar bien, pero estoy preocupado por una condición de carrera imprevista o por la administración de la memoria. – roland

+0

@roland. No creo que este sea un método seguro porque un NSOperationQueue puede usar varios subprocesos (incluso si su maxConcurrentOperationCount es 1). Cuando está utilizando el mecanismo de contexto padre/hijo, tendrá menos problemas de concurrencia porque siempre es el contexto principal el que accede a la tienda. – FKDev

Cuestiones relacionadas