Swift - Making a Button for UITableViewCell with .addTarget

Viewed 1060

I'm trying to make two different buttons for each cell that I create in my table view. One of the buttons is a + button that will increment a label. In my testing however I cannot get the function to work. My current error says

Argument of #selector does not refer to an '@objc' method, property, or initializer

I feel like I'm implementing the .addTarget method completely wrong but I am new. Here is my code:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let item = items[indexPath.section]

    let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as! AddItemCell

    cell.setCell(item: item)

    let itemAmount = cell.itemAmount as UILabel?

    cell.addButton.addTarget(self, action: #selector(addItem(sender:cell.addButton,forLabel:itemAmount!)), for: .touchUpInside)

}


@objc func addItem(sender: UIButton, forLabel label:UILabel) {

    print("Add Button Clicked")

}
2 Answers

You are using selector syntax incorrectly:

action: #selector(addItem(sender:cell.addButton,forLabel:itemAmount!))

Just say:

action: #selector(addItem)

Then, however, you will face a new problem. You think that somehow you can cause this button to call something called addItem(sender:forLabel:). You can't. Change the declaration of addItem to addItem(_ sender:UIButton). That is the only kind of function a button tap can call.

You will thus have the sender (the button), but you must figure out from there what the label is. (And this should be easy, because, knowing the button, you know the cell, and knowing the cell, you know the label.) You cannot pass the label as a parameter in response to the button tap — but you don't need to.

You need to create callback function in you cell

class AddItemCell: UITableViewCell {

    var buttonClickCallback:(() -> Void)?

    @IBAction func onButtonClick(_ sender:Any) {
        buttonClickCallback?()
    }
}

and assign buttonClickCallback in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let item = items[indexPath.section]
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as! AddItemCell
    cell.setCell(item: item)
    let itemAmount = cell.itemAmount as UILabel?
    cell.buttonClickCallback = {
        self.addItem(sender:cell.addButton,forLabel:itemAmount!)
    } 
}
Related