Добавление данных в NSFetchedResultsController во время цикла поиска или создания - PullRequest
0 голосов
/ 07 апреля 2010

У меня есть табличное представление, которое управляется NSFetchedResultsController.Однако у меня возникла проблема с операцией поиска или создания.Когда пользователь достигает нижней части моего табличного представления, я запрашиваю у моего сервера другую порцию контента.Если он не существует в локальном кэше, мы создаем его и храним.Однако, если он существует, я хочу добавить эти данные в контроллер полученных результатов и отобразить их.Я не могу понять эту часть.

Вот что я делаю до сих пор:

  1. NSFetchedRequestController при инициализации запросов для последних 100 результатов из базы данных (используя setFetchLimit:).Даже если есть 1000 строк, я хочу, чтобы сначала было доступно только 100.
  2. Передача возвращенного массива значений с моего сервера в NSOperation для обработки.
  3. В операции создайте новый контекст управляемого объекта для работы.
  4. В операции я выполняю итерацию по массиву и выполняю запрос на выборку, чтобы проверить, существует ли объект (основываясь на егоid сервера).
  5. Если объект не существует, мы создаем его и вставляем в контекст управляемого объекта операций.
  6. После завершения итерации мы сохраняем контекст управляемого объекта,который вызывает уведомление о слиянии в моем основном потоке.

Во время слияния вновь созданные объекты из шага 4 вставляются в таблицу, но любой объект, который уже существовал и был только что выбран, - нет.Вот соответствующий код из моей NSOperation

for (NSDictionary *resultsDict in self.results)
{
    NSNumber *dbID = [NSNumber numberWithLong:[[resultsDict valueForKey:@"id"] longValue]];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:kResultEntityName inManagedObjectContext:moc]];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(dbID == %@)", dbID]];

    NSError *error = nil;

    NSManagedObject *newObject = nil;
    // Query the data store to see if the object exists
    newObject = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
    [fetchRequest release];

    // If it doesn't exist, create it.
    if ((tweet == nil))
    {
        // Create the NSManagedObject and insert it into the MOC.  
    }
}

То, что я хочу передать моему основному потоку, - это вновь созданные объекты плюс любые существующие объекты, которые могли быть извлечены в запросе на выборку при каждой итерации цикла.

Я чувствую, что мне чего-то не хватает, и я могу использовать толчок в правильном направлении.

Ответы [ 3 ]

1 голос
/ 07 апреля 2010

В этот момент все объекты, которые ранее не были локально кэшированы в моем хранилище базовых данных, появятся, но те, которые существовали ранее, не будут отправлены в поездку.

Можете ли вы объяснить это немного? Я не уверен, что вы подразумеваете под теми, которые существовали ранее. Это те объекты, которые не соответствуют фильтру в вашей таблице, которые теперь работают после извлечения или вы говорите, что предыдущие объекты исчезают из таблицы?

Кроме того, как вы реализуете методы делегата для NSFetchedResultsController? Вы выполняете простую перезагрузку таблицы или вставляете / перемещаете строки?

Обновление

Есть несколько способов сделать это, но они потребуют некоторых экспериментов с вашей стороны. Сначала я бы поиграл с идеей «прикасаться» к предметам, которые были извлечены. Возможно, обновление даты 'lastAccessed' или что-то подобное, чтобы эти объекты встретились как объединенные как "обновленные". Я подозреваю, что это самый простой путь.

Кроме того, другим вариантом будет широковещательная рассылка уведомлений об этих объектах обратно в основной поток (используя их NSManagedObjectID в качестве носителя через границы потоков), чтобы вы могли вручную обновить их; Однако это не идеально.

0 голосов
/ 12 апреля 2010

Вот как я это исправил. Перед объединением изменений из моего NSOperation MOC я перебираю значения, хранящиеся в NSUpdatedObjectsKey, и касаюсь их с помощью willAccessValueForKey. Чтобы получить их в ключе NSUpdatedObjects, я воспользовался советом Маркуса выше и добавил свойство lastAccessed, которое я установил на текущую дату в NSOperation, если объект уже существует в постоянном хранилище ..

- (void)mergeChanges:(NSNotification *)notification
{
  NSAssert([NSThread mainThread], @"Not on the main thread");  
  NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];

  for (NSManagedObject *object in updatedObjects)
  {
    [[managedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil];
  }

  [managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
0 голосов
/ 09 апреля 2010

Эй, Джастин, может ли это fetchLimit быть причиной этого?

NSFetchedRequestController когда инициализированные запросы для последних 100 результаты из базы данных (используя setFetchLimit:). Даже если есть 1000 строк, я хочу только 100 доступных сначала.

Вы по-прежнему будете иметь ограничение в 100 результатов на NSFetchedResultsController независимо от того, сколько управляемых объектов вы вставляете и объединяете.

У вас включена сортировка? В этом случае некоторые из вставленных управляемых объектов могут отображаться, поскольку они смещают некоторые из существующих 100 из-за упорядочения результатов.

Я прошел через те же проблемы с извлечением «страниц» результатов, и применил ограничение на нижнюю границу для моей выборки (используя атрибут sorted в NSComparisonPredicate) и скорректировал это с последним элементом в самая последняя «страница» результатов.

Я также попробовал подход fetchLimit, и это тоже сработало. Вам не нужно удалять и перестраивать NSFetchedResultsController, вы можете просто настроить fetchLimit для fetchRequest:

tableMaxItems += 100;
[myFRC.fetchRequest setFetchLimit:tableMaxItems];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...