Search code examples
iosswiftuitableviewgenericsuitoolbar

@IBAction of UIBarButtonItem not being called from UIToolbar inside generic cell of tableview


the fact is I have created a generic cell that looks like this:

class GenericCell<T: ProtocolName>: UITableViewCell {

    // Properties ...

    var someThingINeed: T?

    private var toolbar: UIToolbar = {
        let toolbar = UIToolbar()
        toolbar.sizeToFit()
        toolbar.isUserInteractionEnabled = true

        let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(didTapDone))
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(didTapCancel))

        cancelButton.tintColor = .red

        toolbar.setItems([cancelButton, flexibleSpace, doneButton], animated: false)

        return toolbar
    }()

    override var inputAccessoryView: UIView? {
        if someThingINeed != nil {
            return toolbar
        }
        return nil
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    override var canResignFirstResponder: Bool {
        return true
    }

    // Functions ...

    @objc private func didTapDone() {
        // do something...
        resignFirstResponder()
    }

    @objc private func didTapCancel() {
        // do something...
        resignFirstResponder()
    }

}

So to call the cell input view, I execute this code from the UITableViewController that handles the table with the that type of cell:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section == 0 {
        tableView.cellForRow(at: indexPath)?.becomeFirstResponder()
    }
    tableView.deselectRow(at: indexPath, animated: true)
}

The result I get in the execution is both the inputView and the inputAccessoryView showing up but then, when I tap any of both UIBarButtonItem (Cancel or Done), the buttons seem to respond and receive the tap, but no action is called.

I think the reason might be either that a generic Swift class cannot act as a target for a UIView or that a generic Swift class cannot implement @objc functions.

I don't know what else to do, I have tried to add the cell as delegate of the UIToolbar and executing toolbar.translatesAutoresizingMaskIntoConstraints = false and nothing worked.


Solution

  • Ok, so the problem was that I forget to mark the UIToolbar as lazy so I couldn't use class properties and functions.

    I don't know why Xcode didn't warn me about this... I think this could be reported.