我的许多 tableViews 需要一种方法,以便在屏幕上显示最后一个单元格时加载更多数据。为了避免实现相同的方法 100 次,我决定创建自己的 UITableView 基子类,它会在显示最后一个单元格时,为一个方法调用 tableView 委托(delegate)( View Controller ),要求它加载更多数据,并且如果数据加载成功,将重新加载表格 View 。我认为这是相当合理的,尤其是当我的应用程序中几乎每个表格 View 都需要此功能时。
不幸的是,tableView:willDisplayCell:forRowAtIndexPath: 是一个 UITableViewDelegate 方法。而且我很确定,将 UITableView 子类设置为 UITableViewDelegate 是错误的。所以,那将是我需要创建一个基本的 UITableViewController 类。但是如果实现一个基本的 UITableViewController,我可能想在子类中覆盖 tableView:willDisplayCell:forRowAtIndexPath: 。
另外,我的一些 tableViews 嵌入在 ViewController 中,而不是 TableViewController(因为除了 table View 之外还有其他东西),所以这意味着我需要一个单独的 UITableViewController 和 UIViewController 子类。所以这只会让事情变得更复杂。
那么,如何使这个“在显示最后一个单元格时加载更多数据”功能可重复使用(遵循 MVC 指南)?
编辑:所以我想我已经知道如何开始了。我想要一个基本的 TableViewDelegateClass,例如基 TableView 委托(delegate)。然后,我想继承它,覆盖 tableView:willDisplayCell:forRowAtIndexPath: ,但调用 super.tableView:willDisplayCell:forRowAtIndexPath 。现在,我还有一个问题。我想让它重新加载数据。但我觉得在 tableView 委托(delegate)中引用 tableView 是一个坏主意(可能是引用循环)。有没有很好的协议(protocol)解决方案?
EDIT3:我也在考虑另一种方法:
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()
}
}
}
但这看起来有点难看。
Best Answer-推荐答案 strong>
您可以为 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
}
}
编辑:
另一种选择是为所有需要该行为的 ViewControllers 创建一个基础 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 {
}
和:
class ReloadingTableViewController2: BaseViewControllerForReloadingTables {
}
在这些子类中,您有 UITableView ,即 reloadingTableView 。当它的委托(delegate)函数被调用时,父类(super class)中的实现被执行。这样,数据加载和表格重新加载在一个地方处理,但以适合您的每个 ViewControllers 的方式处理。
当然,您可以在 BaseViewControllerForReloadingTables 类中添加更多常用功能 - 取决于您的屏幕有多少类似的行为。
希望对你有帮助。
关于ios - 使用默认行为创建更可重用的 UITableView 子类,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/40132837/
|