2016-10-19 5 views
2

多くのmy tableViewには、最後のセルが画面に表示されたときにさらにデータを読み込むメソッドが必要です。同じ方法を100回実行するのを避けるために、UITableViewの独自の基本サブクラスを作成することにしました。最後のセルを表示するときに、メソッドのtableView delegate(ビューコントローラ)を呼び出し、さらにデータをロードするように要求します。データロードが成功した場合は、テーブルビューが再読み込みされます。私はこれは非常に合理的ですが、特に、私のアプリケーションのほとんどすべてのテーブルビューがこの機能を必要とする場合。デフォルトの動作でより再利用可能なUITableViewサブクラスを作成する

残念ながら、tableView:willDisplayCell:forRowAtIndexPath:はUITableViewDelegateメソッドです。そして、私はかなり確信しています、UITableViewサブクラスをUITableViewDelegateにするのは間違っています。だから、私は基本的なUITableViewControllerクラスを作る必要があります。しかし、基底のUITableViewControllerを実装する場合は、おそらくサブクラスでtableView:willDisplayCell:forRowAtIndexPath:をオーバーライドする必要があります。

また、私のtableViewのいくつかはTableViewControllerではなくViewControllerに組み込まれています(テーブルビュー以外のものがあります)ので、別のUITableViewControllerとUIViewControllerサブクラスが必要です。だからこれは物事をもっと複雑にしているだけです。

このように、「最後のセルを表示したときにデータをロードする」機能を再利用できるようにするにはどうすればよいですか?

編集:私はどのように開始するかを考え出したと思います。私は基本的なTableViewDelegateClassを持っていたいと思います。 BaseTableViewDelegate。次に、サブクラス化してtableView:willDisplayCell:forRowAtIndexPath:をオーバーライドしますが、super.tableView:willDisplayCell:forRowAtIndexPathを呼び出します。今、私はまだ問題があります。私はそれがデータをリロードするようにしたい。しかし、私はtableViewデリゲートでtableViewへの参照を持っているような気がする(参考ループかもしれない)悪い考えです。プロトコルを使った素敵なソリューションがありますか?

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() 
     } 
    } 
} 

しかし、これは少し醜いです。

答えて

0

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 
    } 
} 

EDIT: 別のオプションは、その動作を必要とするすべての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 { 

} 

あなたはreloadingTableViewあるUITableViewを持っています。デリゲート関数が呼び出されると、スーパークラスの実装が実行されます。このようにして、データの読み込みとテーブルの再読み込みは1か所で処理されますが、ViewControllersのそれぞれに対して適切な方法で処理されます。

もちろん、BaseViewControllerForReloadingTablesクラスにもっと一般的な機能を追加することができます。画面にどれほど類似した動作があるかによって異なります。

希望します。

+0

おそらく、プロトコルを継承する方がいいでしょうね。だから、私はデフォルトのものかカスタムなものかのどちらかを選択することができます。しかし、どのようにプロトコルからテーブルビューのリロードを呼び出すことができますか? –

+0

オーバーライドする場合、デフォルト実装を呼び出すことはできますか? –

+0

答えを編集しました。そこを見てください。また、あなたはプロトコルを継承しているわけではなく、あなたは**拡張して**その機能の1つにデフォルトの実装を与えています。 –

関連する問題