菜鸟教程小白 发表于 2022-12-11 17:53:11

ios - 使用默认行为创建更可重用的 UITableView 子类


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

<p>不幸的是,<code>tableView:willDisplayCell:forRowAtIndexPath:</code> 是一个 UITableViewDelegate 方法。而且我很确定,将 UITableView 子类设置为 UITableViewDelegate 是错误的。所以,那将是我需要创建一个基本的 UITableViewController 类。但是如果实现一个基本的 UITableViewController,我可能想在子类中覆盖 <code>tableView:willDisplayCell:forRowAtIndexPath:</code>。 </p>

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

<p>那么,如何使这个“在显示最后一个单元格时加载更多数据”功能可重复使用(遵循 MVC 指南)? </p>

<p>编辑:所以我想我已经知道如何开始了。我想要一个基本的 TableViewDelegateClass,例如基 TableView 委托(delegate)。然后,我想继承它,覆盖 <code>tableView:willDisplayCell:forRowAtIndexPath:</code>,但调用 <code>super.tableView:willDisplayCell:forRowAtIndexPath</code>。现在,我还有一个问题。我想让它重新加载数据。但我觉得在 tableView 委托(delegate)中引用 tableView 是一个坏主意(可能是引用循环)。有没有很好的协议(protocol)解决方案?</p>

<p>EDIT3:我也在考虑另一种方法:</p>

<pre><code>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 &amp;&amp; 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()
      }   
    }
}
</code></pre>

<p>但这看起来有点难看。 </p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>您可以为 <code>UITableViewDelegate</code> 创建一个扩展,并在其中为 <code>tableView:willDisplayCell:forRowAtIndexPath:</code> 编写一个默认实现。然后你的子类的每个实例都会调用这个实现。</p>

<pre><code>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
    }
}
</code></pre>

<p><strong>编辑:</strong>
另一种选择是为所有需要该行为的 <code>ViewControllers</code> 创建一个基础 <code>ViewController</code>。在这种情况下,您不需要继承 <code>UITableView</code>。</p>

<p>你创建一个这样的类:</p>

<pre><code>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()
      }
    }
}
</code></pre>

<p>然后每个需要加载更多数据到表的<code>ViewController</code> 只是从这个类继承。例如:</p>

<pre><code>class ReloadingTableViewController1: BaseViewControllerForReloadingTables {

}
</code></pre>

<p>和:</p>

<pre><code>class ReloadingTableViewController2: BaseViewControllerForReloadingTables {

}
</code></pre>

<p>在这些子类中,您有 <code>UITableView</code>,即 <code>reloadingTableView</code>。当它的委托(delegate)函数被调用时,父类(super class)中的实现被执行。这样,数据加载和表格重新加载在一个地方处理,但以适合您的每个 <code>ViewControllers</code> 的方式处理。</p>

<p>当然,您可以在 <code>BaseViewControllerForReloadingTables</code> 类中添加更多常用功能 - 取决于您的屏幕有多少类似的行为。</p>

<p>希望对你有帮助。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 使用默认行为创建更可重用的 UITableView 子类,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/40132837/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/40132837/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 使用默认行为创建更可重用的 UITableView 子类