如何正确实现 NSFetchedResultsController.controllerDidChange()

How to correctly implement NSFetchedResultsController.controllerDidChange()

我有一个 UIView,其中有一个 UITableView 以及不同的组件。其对应的UIViewControllerviewDidLoad()如下:

Class Foo: UIViewController, NSFetchedResultsControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        /* some other stuff */

        // An instance of a class implementing UITableViewData Source
        // and NSFetchedResultsController. 
        // It also contains the instance of the  
        // NSFetchedResultsController.
        self.namesTable.dataSource = self.namesTableController  
        self.namesTableController.fetchedResultsController.delegate = self
    }

    // For updating the table when its content changes - NSFetchedResultsControllerDelegate
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        self.namesTable.reloadData()
    }

    /* Other functions, etc, etc.... */

}

这种安排工作正常:当我 add/remove 条目 to/from 和 table 时,table 重新加载。

但我认为这不是正确的做法,因为 整个 table 每次 发生任何变化时都会重新加载。好像有点矫枉过正了。

在网上看了几个小时,我什么都没带。谁能指出我这样做的正确方法?还是我做得对?

尽管 "wrong" 与 reloadData() 没有任何关系,但正如您所说,没有必要在每次对象更改时都调用它。您可以通过实施其他 NSFetchedResultsControllerDelegate 函数并使用 beginUpdates()endUpdates() 来仅更新您想要的内容,如下所示:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}


func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    switch type {
    case NSFetchedResultsChangeType.Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    case NSFetchedResultsChangeType.Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
    case NSFetchedResultsChangeType.Move:
        break
    case NSFetchedResultsChangeType.Update:
        tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
    }
}