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で呼び出されると、最新の「name」値を取得してセルの textLabel に設定できます。リロードしない限り、セルに名前が表示されません。セルをクリックするだけでも、名前が表示されます。この動作を再現するには、新しい管理対象オブジェクトを作成し、NSFetchedResultsController で最初に並べ替える名前を付ける必要があることに注意してください。そうすれば、NSFetchedResultsChangeMove は起動しません (セクションをリロードするため、機能します)。
何か不足していますか、それともこれは予想される動作ですか? reloadRowsAtIndexPathsの「議論」により、行、セクション、またはテーブルをリロードせずに、セルの textLabel を単純に設定できるはずだと思うようになりました。