3

I want to reuse the code below

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 3
}

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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return UITableViewCell()
}

I define a protocol :

protocol ConfigDetail: class, UITableViewDataSource{}

extension ConfigDetail{

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 3
}

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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return UITableViewCell()
}

}

but when i use the protocol with a UIViewController, it always tells me i did not conform to protocol UITableViewDataSource, or i have to add @objc before my protocol. But i have struct variables defined in my protocol, @objc may not help. Any solutions?

jhd
  • 1,243
  • 9
  • 21
  • `but when i use the protocol with a UIViewController` How did you use the protocol ? – Tony Nguyen May 30 '16 at 09:37
  • class ViewController:UIViewController, ConfigDetail{ } and then set the tableView`s dataSource to self – jhd May 30 '16 at 09:42
  • Consider to use a subclass rather than a protocol. – vadian May 30 '16 at 09:55
  • 1
    You currently cannot use extensions to provide default implementations for objc protocols, see this Q&A for more info: http://stackoverflow.com/q/31663560/2976878 – Hamish May 30 '16 at 09:56

1 Answers1

2

If you want to implement these data source methods and reuse them, just define a data source class that implements them. And then rather than implementing the delegate methods in the view controller, instantiate a data source object, keep a strong reference to it, and specify it as the data source for the table view.

For example:

class DataSource: NSObject, UITableViewDataSource {

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 3
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
        // configure cell here
        return cell
    }
}

class ViewController: UITableViewController {

    let dataSource = DataSource()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = dataSource
    }

}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • what should i do if it is a UITableViewDelegate? instantiate a UITableViewDelegate? – jhd May 30 '16 at 10:02
  • And it is really not a good solution, i have to transform plenty of data to my dataSource and the data may changeable :( – jhd May 30 '16 at 10:24
  • Re table view delegate, it all depends upon which delegate methods you are implementing and how much reuse there is. You'd probably let your view controller just handle that. Re passing data to the data source, you presumably have some model class that holds the data managed by the view controller and you'd could just pass a reference to that to your data source's initializer. But, frankly, it just sounds like there wasn't as much reuse in these methods as your question suggested, and therefore it might not be a good candidate for abstraction and encapsulation. – Rob May 30 '16 at 17:13