我目前遇到的问题是,当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多少次的解释也会非常有用。
答案 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。如果您遇到类似问题,请随时给我发消息。