objectAtIndex: 0] numberOfObjects]> fetchLimit - PullRequest
3 голосов
/ 21 июля 2010

У меня в настоящее время проблема, когда мой UITableViewController / UITableView, который использует NSFetchedResultsController, отображает около 86 элементов, когда fetchLimit в fetchRequest для FRC равен 4. Я знаю, что 86 элементов удовлетворяют самому извлечению, и я знаю, что причина они появляются потому, что didChangeObject: atIndexPath ... вызывается для каждого из 86, и я вставляю как вид реализации по умолчанию.

Мой вопрос: почему fetchLimit не ограничивает количество объектов, которые NSFetchedResultsController пытается «изменить» (вставьте в этом случае)?

Мой вариант использования приложения заключается в том, что на первой вкладке отображаются типичные элементы канала, которые я получаю (в боковом потоке) при запуске приложения. Я сохраняю их в CoreData в отдельном контексте, который в конечном итоге сливается с контекстом основного потока и инициирует обратные вызовы FRC для того, что изменилось. Мой вопрос относится конкретно к первоначальному случаю, когда никаких предметов не существует.


Вот мой запрос fetch:

    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
fetchRequest.entity = [NSEntityDescription entityForName:ENTITY_CONTENT_ITEM inManagedObjectContext:managedObjectContext];

// Set a limit on the number of items returned
[fetchRequest setFetchLimit:4];

// Set a Predicate to limit the fetch to featured items only
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"featured == YES AND contentType == %d", contentType]];

// Set the sort descriptors
NSSortDescriptor *sortDateDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"sortDate" ascending:NO] autorelease];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDateDescriptor]];

Приведенный выше contentType - это просто способ выделить то, что должно отображаться на этой вкладке по сравнению с другими вкладками. Featured - это логическое свойство элемента, которое больше похоже на выключатель для отображения.

Вот мой didChangeObject:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
  switch(type) {
    case NSFetchedResultsChangeInsert:
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
      break;
    case NSFetchedResultsChangeDelete:
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
      break;
    case NSFetchedResultsChangeUpdate:
      [tableView cellForRowAtIndexPath:indexPath];
      break;
    case NSFetchedResultsChangeMove:
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
       // Reloading the section inserts a new row and ensures that titles are updated appropriately.
       [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
       break;
  }
}

Я знаю, что будет сложно ответить на этот вопрос, но даже объяснение того, как FRC решает, сколько раз вызывать didChangeObject, было бы очень полезно.

1 Ответ

1 голос
/ 28 июля 2010

https://devforums.apple.com/thread/60319?tstart=0

Для тех, кто может получить доступ к этому, проверьте это. Разработчик Apple дает хороший, быстрый обзор изменений в стеке CoreData / NSFetchedResultsController / UITableViewController в iOS4.0.

В 3.2 и 4.0 были внесены изменения для улучшения кэширования и производительности, а также для исправления известных проблем. Постоянное кэширование гораздо более агрессивно, поэтому люди, неправильно использующие cacheName, столкнулись с проблемами. Если вместо этого для cacheName задано значение nil или очистить использование и вызвать + deleteCacheWithName, то решения этого будут. Пересчет раздела был улучшен для выполнения большего количества вычислений через базу данных, а не в памяти, когда это возможно. Секционирование запускается всякий раз, когда кеш перестраивается (или, если не используется кеш, когда вызывается executeFetch). Временное решение .description заставляет keypath ссылаться на немоделируемое свойство (метод -description), которое заставляет вычисления раздела работать в памяти, так как БД ничего не знает о -description.

В 4.0 также были внесены изменения в UITableView, чтобы исправить ряд проблем, связанных с обратными вызовами делегатов UITableViewController. Люди, которым нужно было использовать -reloadData в более ранних выпусках iOS, чтобы обойти проблемы, должны иметь возможность использовать более мелкозернистые обратные вызовы на iOS4.

-BenT (Apple)

Учитывая это, я добавил .description в мой sectionNameKeyPath в моем вызове fetchedResultsController initWithFetchRequest. Это, очевидно, заставляет вычислять разделы в памяти, а не на диске, что исправило проблему с моими разделами, считающими, что у них было больше элементов, чем у них.

Это работает для 4.0, а в 3.0 я просто вызываю reloadData из обратного вызова controllerDidChangeContent. Не стесняйтесь отправить мне сообщение, если у вас есть подобные проблемы.

...