2011-12-26 18 views
35

iOS 5 introdujo una nueva forma a buscar rápidamente los datos en un subproceso de fondo inicializando el MOC usando NSPrivateQueueConcurrencyType y luego hacer la pelota en performBlock:NSPrivateQueueConcurrencyType de Datos Básicos y compartir objetos entre hilos

Una de las reglas de oro de Core Los datos indican que no puede compartir un objeto gestionado entre hilos/colas. ¿Todavía es el caso con performBlock:? Es la siguiente:

[context performBlock:^{ 
    // fetch request code 

    NSArray *results = [context executeFetchRequest:request error:nil]; 

    dispatch_async(dispatch_get_main_queue(), ^(void) { 
     Class *firstObject = [results objectAtIndex:0]; 
     // do something with firstObject 
    }); 
}]; 

siendo inaceptable ya que estoy compartiendo mis resultados de la matriz/objetos entre la cola y la cola bg principal? ¿Todavía necesito usar los ID de objeto administrado para hacer eso?

Respuesta

64

Cuando se utiliza NSPrivateQueueConcurrencyType que tiene que hacer nada que toca ese contexto o cualquier objeto que pertenece a ese contexto dentro del método -performBlock:.

Su código anterior es ilegal porque está devolviendo esos objetos a la cola principal. La nueva API le ayuda en la solución de esto, sin embargo: Se crea un contexto que está asociada con la cola principal, es decir, con NSMainQueueConcurrencyType:

// Assume we have these two context (They need to be set up. Assume they are.) 
NSManagedObjectContext *mainMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease]; 
NSManagedObjectContext *backgroundMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; 

// Now this can safely be called from ANY thread: 
[backgroundMOC performBlock:^{ 
    NSArray *results = [backgroundMOC executeFetchRequest:request error:nil]; 
    for (NSManagedObject *mo in results) { 
     NSManagedObjectID *moid = [mo objectID]; 
     [mainMOC performBlock:^{ 
      NSManagedObject *mainMO = [mainMOC objectWithID:moid]; 
      // Do stuff with 'mainMO'. Be careful NOT to use 'mo'. 
     }]; 
    } 
}]; 

Esto se hace menos confuso si se mueve el interior [mainMOC performBlock:] llamada en su propio método. También es posible que desee pasar una matriz de Id. De objetos al contexto del subproceso principal en lugar de ejecutar un bloque para cada Id. De objeto. Depende de tus necesidades.

+0

¿Cuál es la fuente de esta información? Esto es ciertamente lo que esperaría que fuera el caso, pero la documentación de Apple solo establece que debe hacer operaciones de MOC en el bloque. No es explícito sobre los OM creados en el bloque. –

+14

MOs pertenecen al contexto. No * son * seguros para hilos y, por lo tanto, solo deben tocarse dentro de la cola del contexto al que pertenecen. No está claro desde la documentación, pero eso es lo que intentó decir. Tengo esta información del equipo de Core Data. –

+0

¿Dónde está la documentación? ¿Alguien tiene un enlace? – djskinner

3

Como explica Daniel Eggert, este sigue siendo definitivamente el caso. La excepción es para NSMainQueueConcurrencyType, donde también puede usar el contexto del objeto administrado y los objetos de forma segura en el hilo principal (así como de otros hilos a través del mecanismo performBlock). ¡La utilidad de esto no puede ser subestimada!

iOS 5 también introdujo el concepto de contextos principales, que también simplifica enormemente las operaciones en segundo plano y elimina la necesidad de preocuparse por usar notificaciones para propocionar cambios entre hilos.

El WWDC 2012 video "Session 214 - Core Data Best Practices" entra en muchos más detalles sobre ambos temas y es muy completo. El video es esencial para cualquiera que use Core Data.

+1

Hasta donde puedo decir, NSMainQueueConcurrencyType es equivalente a crear un NSManagedObjectContext a partir del subproceso principal, y NO es más seguro para subprocesos que cualquier otro contexto. ¿Dónde encontraste que puedes usarlo "desde otros hilos mediante el mecanismo performBlock"? – nevyn

+0

@nevyn En el video WWDC 2012 "Sesión 214 - Mejores prácticas de datos centrales". - [NSManagedObjectContext performBlock:] es el mecanismo exacto al que me refiero. – JosephH

+0

También está en los documentos para NSManagedOBjectContext: "Si su código se está ejecutando en el hilo principal, puede invocar directamente los métodos en los contextos principales del estilo de cola en lugar de usar la API basada en bloques". – ctietze

Cuestiones relacionadas