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 之间的索引差异造成的。它们最初应该匹配,如果您只删除最后一个项目应该没问题,但任何其他删除都会导致它们不同步。