NSFetchedResultsControllerDelegate 在错误的 indexPath 上动画删除
NSFetchedResultsControllerDelegate animating deletion on wrong indexPath
前提:我有一个UITableViewController
符合NSFetchedResultsControllerDelegate
。我还有一个获取结果控制器和托管对象上下文作为控制器中的变量。我的 tableView
显示一个 table,其中包含来自获取的结果控制器的一部分核心数据对象。
我要实现的是滑动删除。选择删除的对象实际上被删除了,但是错误的 indexPath 正在被动画删除,我不知道为什么。我目前有以下我认为相关的方法:
// This method is being called in viewDidLoad, adding all of the CoreData objects to an array called fetchedResults.
func performFetch() {
do { try fetchedResultsController?.performFetch()
fetchedResults = fetchedResultsController?.fetchedObjects as! [Date]
} catch let error as NSError {
print(error.localizedDescription)
}
}
// tableViewDataSource methods
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let objectToDelete = fetchedResults[indexPath.row]
fetchedResultsController?.managedObjectContext.deleteObject(objectToDelete)
print("commitEditingStyle-indexPath = \(indexPath)")
do { try managedContext.save()
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
// NSFetchedResultsControllerDelegate methods
func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject object: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Delete:
if let indexPath = indexPath {
print("didChangeObject indexPath = \(indexPath)")
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
default:
return
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableView.endUpdates()
}
如您所见,我打印了 tableView:commitEditingStyle
方法和 controller:didChangeObject
方法的 indexPath。这是 2 个打印语句:
commitEditingStyle-indexPath = {长度 = 2,路径 = 0 - 3}
didChangeObject-indexPath = {长度 = 2,路径 = 0 - 0}
为什么 didChangeObject
方法选择了错误的 indexPath?当我滑动以删除对象时,对象在正确的 indexPath 处被删除(在本例中为 3...),但动画删除的 table 视图单元格是 indexPath 0(我的第一个单元格 table 看法)。给出了什么?
从您的代码中删除对 fetchedResults
的所有使用。您正在缓存 FRC 知道的初始对象集,但您没有跟踪该缓存中的添加或删除。缓存也是一种内存浪费,因为您始终可以从 FRC 中准确获取您想要的内容,而且它还会跟踪更改。
因此,您看到的应该是随机差异,是由于缓存数组和 FRC 之间的索引差异造成的。它们最初应该匹配,如果您只删除最后一个项目应该没问题,但任何其他删除都会导致它们不同步。
前提:我有一个UITableViewController
符合NSFetchedResultsControllerDelegate
。我还有一个获取结果控制器和托管对象上下文作为控制器中的变量。我的 tableView
显示一个 table,其中包含来自获取的结果控制器的一部分核心数据对象。
我要实现的是滑动删除。选择删除的对象实际上被删除了,但是错误的 indexPath 正在被动画删除,我不知道为什么。我目前有以下我认为相关的方法:
// This method is being called in viewDidLoad, adding all of the CoreData objects to an array called fetchedResults.
func performFetch() {
do { try fetchedResultsController?.performFetch()
fetchedResults = fetchedResultsController?.fetchedObjects as! [Date]
} catch let error as NSError {
print(error.localizedDescription)
}
}
// tableViewDataSource methods
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let objectToDelete = fetchedResults[indexPath.row]
fetchedResultsController?.managedObjectContext.deleteObject(objectToDelete)
print("commitEditingStyle-indexPath = \(indexPath)")
do { try managedContext.save()
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
// NSFetchedResultsControllerDelegate methods
func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject object: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Delete:
if let indexPath = indexPath {
print("didChangeObject indexPath = \(indexPath)")
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
default:
return
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableView.endUpdates()
}
如您所见,我打印了 tableView:commitEditingStyle
方法和 controller:didChangeObject
方法的 indexPath。这是 2 个打印语句:
commitEditingStyle-indexPath = {长度 = 2,路径 = 0 - 3}
didChangeObject-indexPath = {长度 = 2,路径 = 0 - 0}
为什么 didChangeObject
方法选择了错误的 indexPath?当我滑动以删除对象时,对象在正确的 indexPath 处被删除(在本例中为 3...),但动画删除的 table 视图单元格是 indexPath 0(我的第一个单元格 table 看法)。给出了什么?
从您的代码中删除对 fetchedResults
的所有使用。您正在缓存 FRC 知道的初始对象集,但您没有跟踪该缓存中的添加或删除。缓存也是一种内存浪费,因为您始终可以从 FRC 中准确获取您想要的内容,而且它还会跟踪更改。
因此,您看到的应该是随机差异,是由于缓存数组和 FRC 之间的索引差异造成的。它们最初应该匹配,如果您只删除最后一个项目应该没问题,但任何其他删除都会导致它们不同步。