objectAtIndex:0] numberOfObjects]> fetchLimit

时间:2010-07-21 17:45:01

标签: iphone objective-c uitableview nsfetchedresultscontroller nsfetchrequest

我目前遇到的问题是,当FRC的fetchRequest上的fetchLimit为4时,使用NSFetchedResultsController的UITableViewController / UITableView显示大约86个项目。我知道有86个项目满足fetch本身,我知道原因它们出现的原因是因为为86中的每一个调用了didChangeObject:atIndexPath ...而且我插入了一个默认实现。

我的问题是为什么fetchLimit不限制NSFetchedResultsController尝试“更改”的对象数(在这种情况下插入)?

我的应用程序用例是第一个选项卡显示我在应用程序启动时(侧面线程)获得的典型Feed项。我在一个单独的上下文中将它们保存到CoreData,最终合并到主线程的上下文并启动更改后的FRC回调。我的问题特别针对没有项目的初始案例。


这是我的fetchRequest:

    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 个答案:

答案 0 :(得分:1)

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

对于可以访问此功能的用户,请查看。苹果开发人员对iOS4.0中CoreData / NSFetchedResultsController / UITableViewController堆栈的更改进行了简要快速的总结。

  

3.2和4.0中进行了更改以改进缓存和性能以及修复已知问题。持久性缓存更具攻击性,因此滥用cacheName的人遇到了麻烦。将cacheName设置为nil,或清理用法并在适当时调用+ deleteCacheWithName是解决方案。改进了部分重新计算,以便尽可能通过数据库而不是内存执行更多计算。重建缓存时(或者如果不使用缓存,则调用performFetch时)将执行分段触发器。 .description解决方法使得keypath引用了一个未建模的属性(-description方法),它导致节计算在内存中工作,因为db不知道任何关于-description的内容。

     

在4.0中,还对UITableView进行了更改,以修复涉及UITableViewController委托回调的许多问题。需要在早期iOS版本上使用-reloadData来解决问题的人应该能够在iOS4上使用更细粒度的回调。

     

-BenT(Apple)

鉴于此,我在我的fetchedResultsController initWithFetchRequest调用中将.description添加到了sectionNameKeyPath。这显然使得部分计算发生在内存而不是磁盘上,这解决了我的部分认为他们有比他们更多的项目的问题。

适用于4.0,而在3.0中我只是从controllerDidChangeContent回调中调用reloadData。如果您遇到类似问题,请随时给我发消息。