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