que estoy haciendo operaciones en una cola GCD despacho en un NSManagedObjectContext define así:NSSortDescriptor de NSFetchRequest no funcionar después de guardar contexto
- (NSManagedObjectContext *)backgroundContext
{
if (backgroundContext == nil) {
self.backgroundContext = [NSManagedObjectContext MR_contextThatNotifiesDefaultContextOnMainThread];
}
return backgroundContext;
}
MR_contextThatNotifiesDefaultContextOnMainThread
es un método de MagicalRecord:
NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:[NSManagedObjectContext MR_defaultContext]];
return context;
Después buscando mis objetos y dándoles la posición de cola correcta, los registro y el orden es correcto. Sin embargo, el segundo registro parece ser completamente aleatorio, el descriptor de clasificación claramente no está funcionando.
He reducido el problema a [self.backgroundContext save:&error]
. Después de guardar el contexto de fondo, las descripciones de clasificación están rotas.
dispatch_group_async(backgroundGroup, backgroundQueue, ^{
// ...
for (FooObject *obj in fetchedObjects) {
// ...
obj.queuePosition = [NSNumber numberWithInteger:newQueuePosition++];
}
NSFetchRequest *f = [NSFetchRequest fetchRequestWithEntityName:[FooObject entityName]];
f.predicate = [NSPredicate predicateWithFormat:@"queuePosition > 0"];
f.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"queuePosition" ascending:YES]];
NSArray *queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil];
for (FooObject *obj in queuedObjects) {
DLog(@"%@ %@", obj.queuePosition, obj.title);
}
if ([self.backgroundContext hasChanges]) {
DLog(@"Changes");
NSError *error = nil;
if ([self.backgroundContext save:&error] == NO) {
DLog(@"Error: %@", error);
}
}
queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil];
for (FooObject *obj in queuedObjects) {
DLog(@"%@ %@", obj.queuePosition, obj.title);
}
});
No tengo idea de por qué el descriptor de ordenación no funciona, ¿algún experto de Core Data quiere ayudar?
Actualización:
El problema no se produce en IOS 4. Creo que la razón es en algún lugar de la diferencia entre el aislamiento del hilo y modos de cola privada. MagicalRecord utiliza automáticamente el nuevo patrón de concurrencia que parece comportarse de manera diferente.
Actualización 2:
El problema se ha resuelto mediante la adición de un ahorro del contexto de fondo:
if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) {
DLog(@"Changes");
NSError *error = nil;
if ([[NSManagedObjectContext MR_contextForCurrentThread] save:&error] == NO) {
DLog(@"Error: %@", error);
} else {
NSManagedObjectContext *parent = [NSManagedObjectContext MR_contextForCurrentThread].parentContext;
[parent performBlockAndWait:^{
NSError *error = nil;
if ([parent save:&error] == NO) {
DLog(@"Error saving parent context: %@", error);
}
}];
}
}
Actualización 3:
MagicalRecord ofrece un método para guardar de forma recursiva un contexto, ahora mi código se ve así:
if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) {
DLog(@"Changes");
[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveWithErrorHandler:^(NSError *error) {
DLog(@"Error saving context: %@", error);
}];
}
La culpa es mía por no usarlo en el primer lugar ...
Sin embargo, no sé por qué que esto ayude y le encantaría tener una explicación.
Gracias por su contribución, experimenté un poco más con el aislamiento de subprocesos solamente, pero preferiría utilizar colas privadas en iOS 5. Durante las pruebas creo que encontré un error. El contexto save del padre se invoca en el hilo del contexto secundario, lo que genera problemas al guardar recursivamente desde un contexto GCD. He enviado una solicitud de extracción: https://github.com/magicalpanda/MagicalRecord/pull/159 – tim