Базовая структура данных: как эффективно обновлять локальную информацию при изменениях из сети?

В моем приложении есть неэффективность, которую я хотел бы понять и исправить.

Мой алгоритм:

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

Я выполняю проверку строк A и B, создавая предикатный запрос с ключом соответствующего объекта, который является частью моей схемы. Я вижу, что и A (всегда), и B (если выполнение разветвляется на эту часть) генерируют SQL-выбор, например:

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,0071 с для запроса - это нормально на устройстве 3GS, но если вы добавите 100 из них, вы просто получите блокиратор 700 мс.

В моем коде я использую помощника, чтобы сделать эти выборки:

- (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
}

Я чувствую, что это неправильно, и я должен сделать проверку другим способом. Он должен попадать в базу данных только один раз и впоследствии должен быть из памяти, верно? (SQL выполняется даже для тех объектов, которые, я знаю, существуют локально и должны были быть загружены в память с помощью предыдущих запросов.) Но, если у меня есть только myObjectId из внешнего источника, это лучшее, что я могу придумать.

Поэтому, возможно, вопрос заключается в следующем: если у меня есть myObjectId (свойство Core Data int64 в MyObject), как мне правильно проверить, существует ли соответствующий локальный объект в хранилище компакт-дисков или нет? Предварительно загрузить весь набор возможных совпадений, а затем предсказать локальный массив?

(Одним из возможных решений является перемещение этого в фоновый поток. Это было бы хорошо, за исключением того, что когда я получаю изменения из потока и делаю [moc mergeChangesFromContextDidSaveNotification: aNotification]; (получение измененных объектов из фонового потока посредством уведомления), это еще блоки.)

Ответы на вопрос(6)

Ваш ответ на вопрос