如何正确重构 2 个 ViewController 的重复代码?
How to properly refactor repeated code of 2 ViewControllers?
我有 1 个带有 CustomTableView 类型的 UIViewController 和 1 个带有普通 UITableView 类型的 UITableViewController。两者都符合 NSFetchedResultsControllerDelegate
并使用重复代码实现其委托方法。现在它在扩展中。
是否可以将该代码移出到单独的 swift 文件中?我试图用 class NSFetchedResultsView 将它移动到单独的文件,但是当我将该委托方法复制到新文件时,它对它的方法中的 tableView 一无所知...
如何正确分离这些方法?
我要分离的委托方法:
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
if let indexPath = indexPath {
tableView.reloadRows(at: [indexPath], with: .none)
}
case .move:
if let indexPath = indexPath, let newIndexPath = newIndexPath {
tableView.moveRow(at: indexPath, to: newIndexPath)
}
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .none)
}
case .insert:
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .none)
}
default:
tableView.reloadData()
}
}
您可以创建一个可以指定为委托的对象
class CommonFetchResultDelegate: NSFetchedResultsControllerDelegate {
var tableView: UITableView
// make init that takes the table view
init(tableView: TableView) {
self.tableView = tableView
}
// !!!implement all the other delegate functions!!!
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
if let indexPath = indexPath {
tableView.reloadRows(at: [indexPath], with: .none)
}
case .move:
if let indexPath = indexPath, let newIndexPath = newIndexPath {
tableView.moveRow(at: indexPath, to: newIndexPath)
}
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .none)
}
case .insert:
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .none)
}
default:
tableView.reloadData()
}
}
}
// then in the view controller
var myDelegate: CommonFetchResultDelegate?
override viewDidLoad() {
super.viewDidLoad()
self.myDelegate = CommonFetchResultDelegate(tableView: self.tableView)
self.myDelegate = fetchResultController.delegate
}
我有 1 个带有 CustomTableView 类型的 UIViewController 和 1 个带有普通 UITableView 类型的 UITableViewController。两者都符合 NSFetchedResultsControllerDelegate
并使用重复代码实现其委托方法。现在它在扩展中。
是否可以将该代码移出到单独的 swift 文件中?我试图用 class NSFetchedResultsView 将它移动到单独的文件,但是当我将该委托方法复制到新文件时,它对它的方法中的 tableView 一无所知...
如何正确分离这些方法?
我要分离的委托方法:
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
if let indexPath = indexPath {
tableView.reloadRows(at: [indexPath], with: .none)
}
case .move:
if let indexPath = indexPath, let newIndexPath = newIndexPath {
tableView.moveRow(at: indexPath, to: newIndexPath)
}
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .none)
}
case .insert:
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .none)
}
default:
tableView.reloadData()
}
}
您可以创建一个可以指定为委托的对象
class CommonFetchResultDelegate: NSFetchedResultsControllerDelegate {
var tableView: UITableView
// make init that takes the table view
init(tableView: TableView) {
self.tableView = tableView
}
// !!!implement all the other delegate functions!!!
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
if let indexPath = indexPath {
tableView.reloadRows(at: [indexPath], with: .none)
}
case .move:
if let indexPath = indexPath, let newIndexPath = newIndexPath {
tableView.moveRow(at: indexPath, to: newIndexPath)
}
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .none)
}
case .insert:
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .none)
}
default:
tableView.reloadData()
}
}
}
// then in the view controller
var myDelegate: CommonFetchResultDelegate?
override viewDidLoad() {
super.viewDidLoad()
self.myDelegate = CommonFetchResultDelegate(tableView: self.tableView)
self.myDelegate = fetchResultController.delegate
}