NSFetchedResultsControllerDelegate 的文档提供了以下示例代码
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
当我创建一个新的 NSManagedObject 时,NSFetchedResultsChangeInsert触发(太棒了!)。当我更改属性的值(用于单元格的标题)时,NSFetchedResultsChangeUpdate会触发。不幸的是,除非我重新加载表格、部分或行,否则新标题不会自动显示。实际上,如果新名称导致结果集以不同的方式排序,则NSFetchedResultsChangeMove会触发并且一切正常,因为提供的代码会重新加载整个部分。
UITableView 有一个方法reloadRowsAtIndexPaths:withRowAnimation所以我尝试在 NSFetchedResultsChangeUpdate 代码块下使用它。它确实有效......但是这个特定方法的文档读起来好像我不需要它(注意最后一行):
重新加载一行会导致表视图向其数据源询问该行的新单元格。该表在为旧行设置动画时为该新单元格设置动画。如果要提醒用户单元格的值正在更改,请调用此方法。但是,如果通知用户并不重要——也就是说,您只想更改单元格显示的值——您可以获取特定行的单元格并设置其新值。
是的,如果我记录正在发生的事情,什么时候
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
在NSFetchedResultsChangeUpdate上调用,它能够检索最新的“名称”值并将其设置在单元格的 textLabel 中。除非我重新加载,否则该名称不会在单元格中呈现。即使我只是单击单元格,也会显示名称。请注意,要重新创建此行为,您必须创建一个新的托管对象,然后为其命名,使其在 NSFetchedResultsController 中排序为 FIRST。这样, NSFetchedResultsChangeMove 就不会触发(它确实有效,因为它重新加载了该部分)。
我错过了什么还是这是预期的行为?reloadRowsAtIndexPaths的“讨论”让我相信我应该能够简单地设置单元格的 textLabel 而无需重新加载行、节或表。