我以为我明白了。但是我在我的应用程序中发现的一个新的崩溃却不是这样。因此,任何人都知道NSFetchedResultsChangeUpdate
当newIndexPath为非零且与indexPath中的 indexPath 不同时真正正确的代码-controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
?
2 回答
我刚刚在更新时遇到了崩溃,newIndexPath
当索引路径与从表中检索单元格所需的索引路径不匹配时,它似乎作为索引路径提供到获取的结果控制器对象中。考虑以下:
- 表视图在索引 0 处有一个包含 15 个项目的部分。
- 索引 13 处的项目(倒数第二个项目)被删除
- 索引 14 处的项目(最后一个项目)已更新
在上述情况下,假设您正在使用[tableView beginUpdates]
和[tableView endUpdates]
在适当的controllerWill/DidChangeContent:
方法中,您将需要使用indexPath
参数从表中检索要更新的单元格(将是第 0 节,索引 14)和newIndexPath
检索对象的参数使用结果控制器(将是第 0 节,索引 13)配置单元格。
我认为它是这样工作的,因为就结果控制器而言,删除似乎已经发生,但在表视图中没有发生(由于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];
}
我希望这是有帮助的!