私はそれを手に入れたと思った。しかし、私のアプリで見つけた新しいクラッシュは、そうではないと言っています。したがって、 newIndexPathがnil以外であり、 ?のindexPathと同じではないNSFetchedResultsChangeUpdate
場合の、本当に正しいコードを知っている人はいますか?-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
2 に答える
更新時にクラッシュが発生しましたnewIndexPath
。インデックス パスがテーブルからセルを取得するために必要なインデックス パスと一致しない場合、フェッチされた結果コントローラー オブジェクトへのインデックス パスとして が提供されているようです。次の点を考慮してください。
- テーブル ビューには、インデックス 0 に 15 項目のセクションがあります。
- インデックス 13 のアイテム (最後から 2 番目のアイテム) が削除されます
- インデックス 14 のアイテム (最後のアイテム) が更新されます
上記の場合、適切なメソッドで[tableView beginUpdates]
およびを使用していると仮定すると、更新するテーブルからセルを取得するパラメータ (セクション 0、インデックス 14) と、オブジェクトを取得するパラメータを使用する必要があります。結果コントローラーからセルを構成します (セクション 0、インデックス 13 になります)。[tableView endUpdates]
controllerWill/DidChangeContent:
indexPath
newIndexPath
結果コントローラーに関する限り、削除は既に発生しているように見えますが、テーブル ビューでは発生していないため (beginUpdates/endUpdates
更新をラップする呼び出しのため)、このように機能すると思います。上記のケースを考慮すればある程度は理解できますが、すべてのドキュメントがこのケースを考慮していないようです。
したがって、質問に対する答えは、パラメーターを使用indexPath
してテーブル ビューからセルを取得し、newIndexPath
パラメーターを使用してフェッチされた結果コントローラーからオブジェクトを取得する必要があるようです。挿入または削除が行われていない場合は、 に合格しているように見えるため、この場合は両方の目的で使用する必要があることに注意しnil
てnewIndexPath
くださいindexPath
。
NSFetchedResultsController のオブジェクトが「同時に」変化して移動する場合は、-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
タイプを送信 しますNSFetchedResultsChangeUpdate
(こちらを参照)。
私の解決策は、タイプが更新され、indexPathがnewIndexPathと等しくないたびに、タイプを移動するように変更することです
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView;
if (controller == self.fetchedResultsController) {
tableView = self.tableView;
}
else {
tableView = self.searchDisplayController.searchResultsTableView;
}
// type is "update" ---> should be "move"
if (type == NSFetchedResultsChangeUpdate && [indexPath compare:newIndexPath] != NSOrderedSame && newIndexPath != nil) {
type = NSFetchedResultsChangeMove;
}
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 fetchedResultsController:controller configureCell:(UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationRight];
break;
}
}
その後、テーブルビューを更新する必要があります
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
[self.tableView reloadData];
}
これがお役に立てば幸いです。