Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing UITableViewDataSource protocol in two different classes

I am not sure this can be done, or if it's even unrecommended.

What I am trying to achieve is the following:

I have a 2 classes classA and classB that have a reference to the same UITableview instance. What I want is for classA to take care of the implementation of the 2 required methods of the UITableViewDataSource protocol:

  • numberOfRowsInSection
  • cellForRowAt

Then I want classB to be able to implement the other optional methods like titleForHeaderInSection for example.

So how can classA have default implementation of some protocol methods, and let classB be the a class that can build on top of what classB has done?

In a way, the problem that I am facing is the following: How can multiple classes be the datasource of a single UITableView?

EDIT: classA will be in a library that I am writing that takes care of building the core parts of the tableView. classB will be used by the 3rd party dev to mainly customise its appearance.

like image 924
Guy Daher Avatar asked Feb 10 '17 16:02

Guy Daher


1 Answers

I think that the only solution without manually redirecting everything is to use the default implementation of protocol methods, e.g. :

protocol MyTableViewProtocol : UITableViewDelegate, UITableViewDataSource {

}

extension MyTableViewProtocol {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
}

And then make ClassB to implement MyTableViewProtocol instead of UITableViewDelegate and UITableViewDataSource.

However, such a solution will not work because protocol extensions are not accessible by Obj-C.

I think a cleaner (and working) solution would be to create the implementation of numberOfRowsInSection and cellForRowAt outside the protocol and just let ClassB to call them inside the delegate method, e.g.:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return MyTable.tableView(tableView: tableView, numberOfRowsInSection: section)
}

Such a solution will be clearer for the user because it will contain less "magic".

Of course, the classic solution is to define your own delegate:

protocol MyTableViewProtocol {
    func myTableView(_ tableView: MyTableView, ...)   
    ...    
}

and redirect everything to it from your delegate.

This solution makes it impossible for ClassB to overwrite delegate function you don't want it to overwrite.

like image 137
Sulthan Avatar answered Nov 04 '22 06:11

Sulthan