La recuperación de datos centrales basada en NSExpression no recupera valores actuales (iOS 5, GCD)

Lo que estoy tratando de hacer

Estoy usando el código a continuación para download datos (tasas de cambio de divisas históricas) de mi server backend (parse.com) al almacén Core Data de mi aplicación.

La aplicación verifica los últimos datos disponibles almacenados localmente y solo obtiene los datos más recientes del server. Si todavía no hay datos almacenados localmente, obtiene todos los datos del server.

La forma en que se configura el código, obtiene los datos en lotes de 100 objects, guarda los objects en Core Data, obtiene la última date más reciente para la que los datos están ahora almacenados localmente (usando NSExpression ) y obtiene el siguiente lote hasta que no haya más Los nuevos objects se dejan en el server ( objects.count = 0 ).

Debido a que la obtención es lenta, decidí ejecutar las búsquedas y los datos de Core Data en un hilo de background (utilizando el nuevo model de Multi-Treading de Core Data proporcionado por iOS 5).

La obtención del server backend funciona bien, pero …

Mi problema

parece que solo esos objects son evaluados por la NSExpression que se almacenan en el disco (físicamente en la database) y no en los objects que todavía están en la memory y se saveán pronto. Por lo tanto, la búsqueda recupera principalmente los valores "antiguos" del disco (memory).

Sin embargo, al usar el siguiente código de búsqueda (sin NSExpression y NSDictionary como tipo de resultado), obtengo los valores actuales y correctos:

 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:localEntityName]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]; request.sortDescriptors = @[sortDescriptor]; NSArray *results = [backgroundContext executeFetchRequest:request error:&error]; ForexHistory *forexHistoryItem = results.lastObject; NSDate *lastLocalDate = forexHistoryItem.date; NSLog(@"last local date results: %@",lastLocalDate); 

¿Qué NSExpression con mi código a continuación, que utiliza NSExpression y el dictionary como resultado de búsquedaType?

Mi pregunta

¿Cómo puedo asegurarme de que la NSExpression que busca la última date disponible localmente devuelve la última date?

El código

 - (void)seedForexHistoryInManagedObjectContext:(NSManagedObjectContext*)context { NSString* const localEntityName = @"ForexHistory"; NSString* const parseEntityName = localEntityName; NSString* const parseDateIdentifier = @"date"; NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"date"]; NSExpression *maxPeriodExpression = [NSExpression expressionForFunction:@"max:" arguments:@[keyPathExpression]]; NSString *expressionName = @"maxDate"; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = expressionName; expressionDescription.expression = maxPeriodExpression; expressionDescription.expressionResultType = NSDateAttributeType; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:localEntityName]; request.propertiesToFetch = @[expressionDescription]; request.resultType = NSDictionaryResultType; NSArray *currencies = @[@"AUD",@"EUR",@"NZD",@"GBP",@"BRL",@"CAD",@"CNY"]; dispatch_queue_t downloadQueue; downloadQueue = dispatch_queue_create("download", NULL); // create serial dispatch queue NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; moc.parentContext = context; dispatch_async(downloadQueue,^{ [moc performBlockAndWait:^{ NSArray *objects; do { NSError *error; NSArray *dateResults = [moc executeFetchRequest:request error:&error]; NSAssert(dateResults.count == 1,@"Request error!"); NSDate *lastLocalDate = dateResults.lastObject[expressionName]; NSLog(@"last local date results: %@",lastLocalDate); PFQuery *query = [PFQuery queryWithClassName:parseEntityName]; query.limit = 100; [query orderByAscending:parseDateIdentifier]; if (lastLocalDate) [query whereKey:parseDateIdentifier greaterThan:lastLocalDate]; // else query all objects = [query findObjects]; [objects enumerateObjectsUsingBlock:^(PFObject *obj, NSUInteger idx, BOOL *stop) { ForexHistory *forexHistory = [NSEntityDescription insertNewObjectForEntityForName:localEntityName inManagedObjectContext:moc]; forexHistory.date = NULL_TO_NIL(obj[@"date"]); [currencies enumerateObjectsUsingBlock:^(NSString *currency, NSUInteger idx, BOOL *stop) { [forexHistory setValue:NULL_TO_NIL(obj[currency]) forKey:currency.lowercaseString]; }]; }]; NSError *saveError = nil; [moc save:&saveError]; if (!saveError) NSLog(@"%lu forex rates saved successfully.",(unsigned long)objects.count); else NSLog(@"Error when downloading historic forex rates: %@",error.localizedDescription); } while (objects.count > 0); }]; } 

¡Gracias por tu ayuda!

Desafortunadamente, esto no es posible. Consulte la documentation de setIncludesPendingChanges: ::

Consideraciones Especiales

Un valor de YES no es compatible junto con el tipo de resultado NSDictionaryResultType , incluido el cálculo de los resultados agregados (como max y min ). Para los dictionarys, la matriz devuelta por la búsqueda refleja el estado actual en la tienda persistente, y no tiene en count ningún cambio pendiente, inserción o eliminación en el context.

Incluir cambios pendientes: Insertar [request setIncludePendingChanges:YES]; antes de hacer la búsqueda.

Esto garantiza que los cambios no guardados se incluyan en la búsqueda.