7

私はそれを手に入れたと思った。しかし、私のアプリで見つけた新しいクラッシュは、そうではないと言っています。したがって、 newIndexPathがnil以外であり、 ?のindexPathと同じではないNSFetchedResultsChangeUpdate場合の、本当に正しいコードを知っている人はいますか?-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

4

2 に答える 2

10

更新時にクラッシュが発生しましたnewIndexPath。インデックス パスがテーブルからセルを取得するために必要なインデックス パスと一致しない場合、フェッチされた結果コントローラー オブジェクトへのインデックス パスとして が提供されているようです。次の点を考慮してください。

  1. テーブル ビューには、インデックス 0 に 15 項目のセクションがあります。
  2. インデックス 13 のアイテム (最後から 2 番目のアイテム) が削除されます
  3. インデックス 14 のアイテム (最後のアイテム) が更新されます

上記の場合、適切なメソッドで[tableView beginUpdates]およびを使用していると仮定すると、更新するテーブルからセルを取得するパラメータ (セクション 0、インデックス 14) と、オブジェクトを取得するパラメータを使用する必要があります。結果コントローラーからセルを構成します (セクション 0、インデックス 13 になります)。[tableView endUpdates]controllerWill/DidChangeContent:indexPathnewIndexPath

結果コントローラーに関する限り、削除は既に発生しているように見えますが、テーブル ビューでは発生していないため (beginUpdates/endUpdates更新をラップする呼び出しのため)、このように機能すると思います。上記のケースを考慮すればある程度は理解できますが、すべてのドキュメントがこのケースを考慮していないようです。

したがって、質問に対する答えは、パラメーターを使用indexPathしてテーブル ビューからセルを取得し、newIndexPathパラメーターを使用してフェッチされた結果コントローラーからオブジェクトを取得する必要があるようです。挿入または削除が行われていない場合は、 に合格しているように見えるため、この場合は両方の目的で使用する必要があることに注意しnilnewIndexPathくださいindexPath

于 2013-08-08T22:02:50.143 に答える
1

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];
}

これがお役に立てば幸いです。

于 2014-05-14T11:41:45.470 に答える