如何正确实现 NSFetchedResultsController.controllerDidChange()
How to correctly implement NSFetchedResultsController.controllerDidChange()
我有一个 UIView
,其中有一个 UITableView
以及不同的组件。其对应的UIViewController
有viewDidLoad()
如下:
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)
}
}
我有一个 UIView
,其中有一个 UITableView
以及不同的组件。其对应的UIViewController
有viewDidLoad()
如下:
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)
}
}