3

I need to set up different objects based on certain conditions as the datasource & delegate for table view.

But I am not able to assign tableview's datasource/delegate as it throws some errors.

Cannot assign a value of type NSObject? to a value of type UITableViewDelegate?

I did check this Q&A but this did not work.

var dataSourceDelegate:NSObject?
class RootViewController: UIViewController {
...
override func viewDidLoad() {
        dataSourceDelegate = TableDataSourceDelegate()
        // Table View
        tableView = UITableView()
        tableView!.setTranslatesAutoresizingMaskIntoConstraints(false)
        tableView!.dataSource = dataSourceDelegate 
        // Cannot assign a value of type NSObject? to a value of type UITableViewDataSource?
        tableView!.delegate = dataSourceDelegate
        // Cannot assign a value of type NSObject? to a value of type UITableViewDelegate?
        view.addSubview(tableView!)

        // Constraints
        var views:[String:UIView] = ["table":tableView!]
        var hTableConstraint = "H:|[table]|"
        var vConstraint = "V:|[table]|"
        view.addConstraintsToView([hTableConstraint, vConstraint], view: view, viewVariables: views)
    }
...
}

This is the datasource/delegate class

class TableDataSourceDelegate:NSObject, UITableViewDataSource, UITableViewDelegate {
    // MARK: Datasource

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

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

    // MARK: Delegates
}

2 Answers 2

3

NSObject? doesn't conforms to UITableViewDelegate, neither to UITableViewDataSource. You should create your protocol like

protocol GeneralDataSource: UITableViewDataSource, UITableViewDelegate {}

And then all data sources should conform that protocol.

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

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

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

Then you can use it like this

var myDataSource: GeneralDataSource?

override func viewDidLoad() {
    super.viewDidLoad()

    self.myDataSource = MyDataSource()
    self.tableView.delegate = self.myDataSource
}
Sign up to request clarification or add additional context in comments.

Comments

1

This is how your TableDataSourceDelegate should look like:

import UIKit

class TableDataSourceDelegate: NSObject {
}

extension TableDataSourceDelegate: UITableViewDataSource {
    @objc func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 0
    }

    @objc func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "defaultCell")
        cell.textLabel?.text = "test"
        return cell
    }
}

extension TableDataSourceDelegate: UITableViewDelegate {
    // your delegate implementation here
}

And view controller implementation

import UIKit

// The typealias definition
typealias TVDataSourceDelegate = protocol<UITableViewDataSource, UITableViewDelegate>

class ViewController: UIViewController {

    var dataSourceDelegate: TVDataSourceDelegate?
    var tableView: UITableView?

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSourceDelegate = TableDataSourceDelegate()
        // Table View
        tableView = UITableView()
        tableView!.translatesAutoresizingMaskIntoConstraints = false
        tableView!.dataSource = dataSourceDelegate
        tableView!.delegate = dataSourceDelegate
        view.addSubview(tableView!)

        // other code ...
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Although, I would recommend to separate dataSource and delegate objects (e.g. put the delegate protocol conforming code into your view controller's code.

1 Comment

I had to create a new class to make it work. This works too but I am accepting the other one as it was posted earlier, wish I could upvote.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.