7

我以为我明白了。但是我在我的应用程序中发现的一个新的崩溃却不是这样。因此,任何人都知道NSFetchedResultsChangeUpdatenewIndexPath为非零且与indexPath中的 indexPath 不同时真正正确的代码-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

4

2 回答 2

10

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

  1. 表视图在索引 0 处有一个包含 15 个项目的部分。
  2. 索引 13 处的项目(倒数第二个项目)被删除
  3. 索引 14 处的项目(最后一个项目)已更新

在上述情况下,假设您正在使用[tableView beginUpdates][tableView endUpdates]在适当的controllerWill/DidChangeContent:方法中,您将需要使用indexPath参数从表中检索要更新的单元格(将是第 0 节,索引 14)和newIndexPath检索对象的参数使用结果控制器(将是第 0 节,索引 13)配置单元格。

我认为它是这样工作的,因为就结果控制器而言,删除似乎已经发生,但在表视图中没有发生(由于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 回答