【问题标题】:objectAtIndex:0] numberOfObjects] > fetchLimitobjectAtIndex:0] numberOfObjects] > fetchLimit
【发布时间】:2010-07-21 17:45:00
【问题描述】:

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

我的问题是为什么 fetchLimit 不限制 NSFetchedResultsController 尝试“更改”(在本例中为插入)的对象数量?

我的应用程序用例是第一个选项卡显示我在应用程序启动时(在侧线程上)获得的典型提要项目。我将它们保存到 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 的次数也会非常有帮助。

【问题讨论】:

    标签: iphone objective-c uitableview nsfetchedresultscontroller nsfetchrequest


    【解决方案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(苹果)

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

    这适用于 4.0,而在 3.0 中,我只需从 controllerDidChangeContent 回调中调用 reloadData。如果您有类似的问题,请随时给我留言。

    【讨论】:

      猜你喜欢
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-21
      相关资源
      最近更新 更多