Luca Becchetti Luca Becchetti - 2 months ago 21
iOS Question

UITableView delegate and datasource in external class does not work

I have a simple project, with UITableView added as subview of the current view, and external tableviewcontroller class that make a delegate and datasource.

The problem is that all work correctly excepted delegate didSelectedRowAtIndexPath, when I click in a single row, all tableview become white, here is the code:

MAIN CLASS:

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.


let cont:Tbcontroller = Tbcontroller()
let tableViewInner = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width-(self.view.frame.width/6), height: 180))
tableViewInner.scrollEnabled = false
tableViewInner.separatorStyle = .None
tableViewInner.allowsSelection = true
tableViewInner.userInteractionEnabled = true
cont.type = 1
cont.setCurrentTableView(tableViewInner)
self.view.insertSubview(tableViewInner, atIndex: self.view.subviews.count+1)

}

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


}


EXTERNAL CLASS DELEGATE DATASOURCE:

import UIKit

class Tbcontroller: UITableViewController {

var type:Int = 1

override func viewDidLoad() {
super.viewDidLoad()


}

func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell

}

func setCurrentTableView(table:UITableView){

self.tableView = table
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}

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

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 4
}

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

let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)

return cell

}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

return 100

}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

print("clicked")

}

}


When I click, I do not see the output "clicked"

Answer

Your main problem is that TbController() get deallocated. dataSource and delegate properties on UITableView are weak. Therefor, because you only assign TbController to a local variable and to the weak properties, it will get deallocated.

Also, the UITableViewController already creates a TableView for you. It is not good practice to "recreate" it. I would rather make use of the TableView in the UITableViewController and add the UITableViewController's view as a subview to your UIViewController's view.

To fix, you need an instance variable for TbController.

Sample code with ivar for TbController and making use of Tbcontroller's UITableView.

 import UIKit

    class ViewController: UIViewController {

    var cont: Tbcontroller = Tbcontroller()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        cont.type = 1
        self.view.addSubview(cont.view)
    }

}

    import UIKit

    class Tbcontroller: UITableViewController {

    var type:Int = 1

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.scrollEnabled = false
        tableView.separatorStyle = .None
        tableView.allowsSelection = true
        tableView.userInteractionEnabled = true

        self.tableView.delegate = self
        self.tableView.dataSource = self
    }

    func getCell() -> UITableViewCell{
        let presentCell: UITableViewCell = UITableViewCell()
        return presentCell

    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 4
    }

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

        let cell = getCell()
        cell.textLabel?.text = "ciao"
        cell.textLabel?.font = UIFont.systemFontOfSize(13)

        return cell

    }

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        return 100

    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        print("clicked")

    }

}