Padrão de dados principais: como atualizar com eficiência informações locais com alterações da rede?

Tenho alguma ineficiência no meu aplicativo que gostaria de entender e corrigir.

Meu algoritmo é:

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object

Estou verificando as linhas A e B criando uma consulta de predicado com a chave do objeto relevante que faz parte do meu esquema. Vejo que A (sempre) e B (se a execução for ramificada nessa parte) geram uma seleção SQL como:

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.

0.0071s para uma consulta são bons em um dispositivo 3GS, mas se você adicionar 100 deles, terá um bloqueador de 700ms.

No meu código, estou usando um auxiliar para fazer essas buscas:

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}

Sinto que isso está errado e devo fazer a verificação de outra maneira. Ele só deve atingir o banco de dados uma vez e deve vir da memória posteriormente, certo? (O SQL é executado mesmo para objetos que, com certeza, existem localmente e deveriam ter sido carregados na memória com consultas anteriores.) Mas, se eu tiver apenas myObjectId de uma fonte externa, é o melhor que posso pensar.

Portanto, talvez a pergunta seja: se eu tenho o myObjectId (uma propriedade Core Data int64 no MyObject), como devo verificar corretamente se o objeto local relevante existe ou não na loja de CDs? Pré-carregar todo o conjunto de correspondências possíveis e predicar uma matriz local?

(Uma solução possível é mover isso para um encadeamento em segundo plano. Isso seria bom, exceto que quando eu obtiver as alterações do encadeamento e fizer [moc mergeChangesFromContextDidSaveNotification: aNotification]; (obtendo objetos alterados do encadeamento em segundo plano por meio de notificação), isso ainda bloqueia.)

questionAnswers(6)

yourAnswerToTheQuestion