Ios 创建具有默认行为的更可重用的UITableView子类

Ios 创建具有默认行为的更可重用的UITableView子类,ios,iphone,swift,uitableview,model-view-controller,Ios,Iphone,Swift,Uitableview,Model View Controller,我的许多表视图都需要一种方法,在屏幕上显示最后一个单元格时加载更多数据。为了避免实现相同的方法100次,我决定创建自己的UITableView基本子类,它将在显示最后一个单元格时,调用tableView委托(视图控制器)以获取方法,要求它加载更多数据,如果数据加载成功,将重新加载表视图。我认为这是相当合理的,尤其是当我的应用程序中几乎每个表视图都需要此功能时 不幸的是,tableView:willDisplayCell:forrowatinexpath:是一个UITableViewDelegat

我的许多表视图都需要一种方法,在屏幕上显示最后一个单元格时加载更多数据。为了避免实现相同的方法100次,我决定创建自己的UITableView基本子类,它将在显示最后一个单元格时,调用tableView委托(视图控制器)以获取方法,要求它加载更多数据,如果数据加载成功,将重新加载表视图。我认为这是相当合理的,尤其是当我的应用程序中几乎每个表视图都需要此功能时

不幸的是,
tableView:willDisplayCell:forrowatinexpath:
是一个UITableViewDelegate方法。我很确定,将UITableView子类设置为UITableViewDelegate是错误的。因此,我需要创建一个基本的UITableViewController类。但是,如果实现一个基本UITableViewController,我可能希望覆盖子类中的
tableView:willDisplayCell:ForRowatineXpath:

另外,我的一些表视图嵌入了ViewController,而不是TableViewController(因为除了表视图之外还有其他东西),因此这意味着我需要一个单独的UITableViewController和UIViewController子类。所以这只会让事情变得更复杂

那么,如何使“在显示最后一个单元格时加载更多数据”功能可重用(遵循MVC准则)

编辑:所以我想我已经知道如何开始了。我想要一个基本的TableViewDelegateClass,例如BaseTableViewDelegate。然后,我想将其子类化,覆盖
tableView:willDisplayCell:forRowAtIndexPath:
,但调用
super.tableView:willDisplayCell:forRowAtIndexPath
。现在,我仍然有一个问题。我想让它重新加载数据。但我觉得在tableView委托中引用tableView是个坏主意(可能是引用循环)。有一个很好的协议解决方案吗

编辑3:我也在考虑另一种方法:

protocol MyTableViewDelegate: UITableViewDelegate {

    func default_tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    func loadMoreData()
}

extension MyTableViewDelegate {

    func default_tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    {
        if(indexPath.section == tableView.numberOfSections - 1 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 )
        {
            self.loadMoreData()
        }
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    {
        self.default_tableView(tableView, willDisplay: cell, forRowAt: indexPath)
        //do something else here that is not done in default_tableView
    }

}

class MyView: UIView, MyTableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    {
        self.default_tableView(tableView, willDisplay: cell, forRowAt: indexPath)
    }

    func loadMoreData()
    {
        loadMoreDataFromServer(){
            tableView.reloadData()
        }   
    }
}

但这看起来有点难看

您可以为
UITableViewDelegate
创建扩展,并在其中为
tableView:willDisplayCell:forRowAtIndexPath:
编写默认实现。然后子类的每个实例都将调用此实现

extension UITableViewDelegate {
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        // do what you need here, each ViewController that conforms to UITableViewDelegate will execute this implementation unless told otherwise
    }
}
编辑: 另一个选项是为所有需要该行为的
ViewController
创建一个基本
ViewController
。在这种情况下,您不需要子类化
UITableView

您可以创建这样的类:

class BaseViewControllerForReloadingTables: UIViewController, UITableViewDelegate {
    private var needToLoadMoreData: Bool = false
    @IBOutlet var reloadingTableView: UITableView!

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if needToLoadMoreData {
            loadMoreData()
        }
    }


    private func loadMoreData() {
        //load data
        //if loading was successful 
        if reloadingTableView != nil {
            reloadingTableView.reloadData()
        }
    }
}
然后,每个需要将更多数据加载到表中的
ViewController
,都是从这个类继承的。例如:

class ReloadingTableViewController1: BaseViewControllerForReloadingTables {

}
以及:

在这些子类中有
UITableView
,它是
reloadingTableView
。调用其委托函数时,将执行超类中的实现。通过这种方式,数据加载和表重新加载在一个位置进行处理,但对每个
视图控制器都采用适当的方式进行处理

当然,您可以向
BaseViewControllerForReloadingTables
类添加更多的常用函数,这取决于您的屏幕有多少类似的行为


希望有帮助。

我想继承协议可能会更好,对吗?因此,我可以选择使用默认值或自定义值。但是,如何从协议调用表视图重载?如果覆盖它,如何调用默认实现?我已经编辑了答案,请看。另外,您不是在继承协议,而是在扩展协议,并为其中一个函数提供一个默认实现。@MaxPevsner这样做有一个问题,我已经厌倦了,我得到了结果。@AhmadF,您的问题与建议的解决方案无关。
class ReloadingTableViewController2: BaseViewControllerForReloadingTables {

}