¿Cómo accedes a NSManagedObjects entre bloques?

Al igual que el título, se explica cómo se accede a un object NSManagedObject que se ha creado en un bloque y luego se debe acceder en el otro. Tengo la siguiente implementación y me preguntaba si es correcta.

__block Person *newPerson; @weakify(self); [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { newPerson = [Person MR_createInContext:localContext]; newPerson.name = @"Bob"; } completion:^(BOOL success, NSError *error) { @strongify(self); // Called on main thread PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:newPerson]; [self.navigationController pushViewController:personVC animated:YES]; }]; 

¿Estoy en lo cierto al no tener que acceder a newPerson desde un localContext en el manejador de finalización porque se ejecutará en el hilo principal?

EDITAR

Parece que la siguiente es la forma propuesta:

 __block NSManagedObjectID *newPersonObjectID; @weakify(self); [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { Person *newPerson = [Person MR_createInContext:localContext]; newPerson.name = @"Bob"; newPersonObjectID = newPerson.objectID; } completion:^(BOOL success, NSError *error) { @strongify(self); // Called on main thread Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID]; PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson]; [self.navigationController pushViewController:personVC animated:YES]; }]; 

Solución

Esta respuesta y comentarios conducen a la siguiente solución. Un TemporaryID se asigna al object mientras se lo guarda y, por lo tanto, cuando se trata de search el object con el TempID se produce una exception.

En lugar de crear una request de búsqueda completamente nueva, lo que se puede hacer es pedir al context que obtenga las identificaciones permanentes temprano y que adquiera la ID permanente del object. Por ejemplo:

 __block NSManagedObjectID *newPersonObjectID; @weakify(self); [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { Person *newPerson = [Person MR_createInContext:localContext]; newPerson.name = @"Bob"; [localContext obtainPermanentIDsForObjects:@[newPerson] error:NULL]; newPersonObjectID = newPerson.objectID; } completion:^(BOOL success, NSError *error) { @strongify(self); // Called on main thread Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID]; PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson]; [self.navigationController pushViewController:personVC animated:YES]; }]; 

No puede pasar directamente los objects gestionados entre contexts. A cada NSManagedObject solo se puede acceder por su propio context.

Deberá pasar su objectID object al bloque de finalización, luego hacer que el context principal obtenga el object llamando a uno de los siguientes methods:

 -(NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID 

Esto creará un error en un object con el ID del object especificado, independientemente de que exista o no en la tienda. Si no existe, todo lo que dispare la falla fallará con una exception.

 -(NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error 

Esto obtendrá el object de la tienda que tiene esa ID o devolverá cero si no existe. A diferencia de objectWithID , el object no será criticado; todos sus attributes se habrán recuperado.

En cualquier caso, su context local debe haber guardado el object Person en la tienda para el context principal para poder getlo.

Puede encontrar más detalles sobre objectID en la Guía de progtwigción de datos básicos

Editar por pregunta que hace el usuario

Esta respuesta y comentarios conducen a la solución correcta. Un TemporaryID se asigna al object mientras se lo guarda y, por lo tanto, cuando se trata de search el object con el TempID se produce una exception.

En lugar de crear una request de búsqueda completamente nueva, lo que se puede hacer es pedir al context que obtenga las identificaciones permanentes temprano y que adquiera la ID permanente del object. Por ejemplo:

 __block NSManagedObjectID *newPersonObjectID; @weakify(self); [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { Person *newPerson = [Person MR_createInContext:localContext]; newPerson.name = @"Bob"; [localContext obtainPermanentIDsForObjects:@[newPerson] error:NULL]; newPersonObjectID = newPerson.objectID; } completion:^(BOOL success, NSError *error) { @strongify(self); // Called on main thread Person *savedPerson = [[NSManagedObjectContext MR_defaultContext] objectWithID:newPersonObjectID]; PersonViewController *personVC = [[PersonViewController alloc] initWithPerson:savedPerson]; [self.navigationController pushViewController:personVC animated:YES]; }]; 

Debería acceder al objectID fuera de su bloque (en el hilo principal, por ejemplo) y luego utilizarlo dentro de su bloque. Algo como:

 NSManagedObjectID *objectID = appDelegate.myObject.objectId; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // use objectID here. }