sto facendo operazioni in una coda GCD messaggio concernente un NSManagedObjectContext definita in questo modo:NSSortDescriptor di NSFetchRequest non funziona dopo contesto Salva
- (NSManagedObjectContext *)backgroundContext
{
if (backgroundContext == nil) {
self.backgroundContext = [NSManagedObjectContext MR_contextThatNotifiesDefaultContextOnMainThread];
}
return backgroundContext;
}
MR_contextThatNotifiesDefaultContextOnMainThread
è un metodo da MagicalRecord:
NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:[NSManagedObjectContext MR_defaultContext]];
return context;
Dopo recuperando i miei oggetti e dando loro la corretta posizione in coda li registro e l'ordine è corretto. Tuttavia, il secondo registro sembra essere completamente casuale, il descrittore di ordinamento chiaramente non funziona.
Ho ristretto il problema a [self.backgroundContext save:&error]
. Dopo aver salvato il contesto, i descrittori di ordinamento vengono interrotti.
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);
}
});
ho idea del perché il descrittore di tipo non funziona, gli esperti Core Data vogliono dare una mano?
Aggiornamento:
Il problema non si verifica su iOS 4. Penso che il motivo è da qualche parte nella differenza tra filo isolamento e le modalità di coda privati. MagicalRecord utilizza automaticamente il nuovo modello di concorrenza che sembra comportarsi diversamente.
Aggiornamento 2:
Il problema è stato risolto con l'aggiunta di un salvataggio del contesto di 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);
}
}];
}
}
Update 3:
MagicalRecord offre un metodo per salvare in modo ricorsivo un contesto, ora il mio codice assomiglia a questo:
if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) {
DLog(@"Changes");
[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveWithErrorHandler:^(NSError *error) {
DLog(@"Error saving context: %@", error);
}];
}
Vergogna su di me per non usarlo in primo luogo ...
Tuttavia, non so il motivo per cui questo aiuta e mi piacerebbe avere una spiegazione.
Grazie per l'input, ho sperimentato un po 'di più solo con l'isolamento del thread ma preferirei usare code private su iOS 5. Durante i test penso di aver trovato un bug. Il salvataggio del contesto genitore viene chiamato sul thread del contesto figlio, il che porta a problemi durante il salvataggio in modo ricorsivo da un contesto GCD. Ho inviato una richiesta di pull: https://github.com/magicalpanda/MagicalRecord/pull/159 – tim