OGeek|极客世界-中国程序员成长平台

标题: ios - 使用默认行为创建更可重用的 UITableView 子类 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 17:53
标题: ios - 使用默认行为创建更可重用的 UITableView 子类

我的许多 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-推荐答案


您可以为 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/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4