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 && 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]