Carlo
Carlo

Reputation: 13

How to use tableView propriety in a UITableViewCell class

In my swift project I have a tableViewController, with class TableViewController, and one prototype cell, with class TableViewCell. Now I want to use: tableView.reloadData(), or other function, in the class TableViewCell. I put a button into the prototype cell, here the code:

class TableViewCell: UITableViewCell {

   let tableViewController = TableViewController()

    @IBAction func actionButton(_ sender: UIButton) {

    tableViewController.tableView.reloadData() // or other function 

}
}

by this method the result is: unexpectedly found nil while unwrapping an optional value. I checked that the class TableViewController is loaded before than the class TableViewCell, so I don't found the problem. Can you help me to find how this error occur?

Upvotes: 1

Views: 34

Answers (2)

Ashley Mills
Ashley Mills

Reputation: 53231

Your actionButton method is creating a new instance of TableViewController each time it's called. It does not refer to the TableViewController which (presumably) is presenting the cells.

You can handle this in a few of ways. A delegate protocol is the "classic" way to do this, or you could use a Swift closure.

Delegate method

In your cell

protocol TableViewCellDelegate: class {
    func tableViewCellDidTapButton(_ tableViewCell: TableViewCell)
}

class TableViewCell: UITableViewCell {

    var weak delegate: TableViewCellDelegate?

    @IBAction func actionButton(_ sender: UIButton) {
        delegate?.tableViewCellDidTapButton(self)
    }
}

In your view controller

class TableViewController: UITableViewController {

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {    
        let cell = dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
        cell.delegate = self
        return cell
    }
}

extension class TableViewController: TableViewCellDelegate {
    func tableViewCellDidTapButton(_ tableViewCell: TableViewCell) {
        let indexPath = indexPath(for: tableViewCell)
        // do something
    }
}

Closure method

In your cell

class TableViewCell: UITableViewCell {

    var didTapButton: Void -> () = { }

    @IBAction func actionButton(_ sender: UIButton) {
        didTapButton()
    }
}

In your view controller

class TableViewController: UITableViewController {

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {    
        let cell = dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
        cell.didTapButton = { 
            // do something with this indexPath
        }
        return cell
    }
}

Upvotes: 1

Somebody
Somebody

Reputation: 733

you can't call TableViewController from other class

you need to use NotificationCenter or protocol

Upvotes: 0

Related Questions