如何在NSFetchedResultsChangeUpdate中使用newIndexPath?

时间:2012-09-15 15:53:50

标签: ios uitableview core-data nsfetchedresultscontroller

我以为我是got it。但是我在我的应用程序中发现的新崩溃说不然。因此当 newIndexPath 为非零并且与NSFetchedResultsChangeUpdate中的 indexPath 不同时,任何人都知道-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:的真正正确的代码吗?

2 个答案:

答案 0 :(得分:9)

我刚刚在更新时遇到崩溃,并且当索引路径与从中检索单元格所需的索引路径不匹配时,似乎newIndexPath被提供为获取的结果控制器对象的索引路径桌子。请考虑以下事项:

  1. 表格视图的索引为0的部分包含15个项目。
  2. 删除索引13处的项目(倒数第二项)
  3. 索引14(最后一项)的项目已更新
  4. 在上述情况下,假设您在相应的[tableView beginUpdates]方法中使用[tableView endUpdates]controllerWill/DidChangeContent:,则需要使用indexPath参数来检索单元格从表更新(将是第0部分,索引14)和newIndexPath参数,以从结果控制器(将是第0部分,索引13)检索要配置单元格的对象。

    我认为它以这种方式工作,因为就结果控制器而言,删除似乎已经发生,但在表视图中没有发生(由于beginUpdates/endUpdates调用包装更新)。如果你考虑上面的情况就行了,但似乎所有文档都没有考虑这种情况。

    因此问题的答案是,您应该使用indexPath参数从表视图中检索单元格,并使用newIndexPath参数从提取的结果控制器中检索对象。请注意,如果没有插入或删除,则nil似乎会传递newIndexPath,因此在这种情况下,您必须同时使用indexPath

答案 1 :(得分:1)

如果NSFetchedResultsController的对象在"同一时间改变并移动" -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:发送类型NSFetchedResultsChangeUpdatesee here)。

我的解决方案是每次更新类型时更改类型以移动并且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];
}

我希望这有用!