2

I've added a button to a specific UITableViewCell. When I select the button, I get a crash:

ButtonTapped libc++abi.dylib: terminating with uncaught exception of type NSException

At the beginning of cellForRowAt, I'm defining the button:

let myButton = UIButton(type: .custom)
myButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
myButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
myButton.tintColor = UIColor.yellow()

For the indexpath.row I attach the button like this:

cell.accessoryView = myButton as UIView

And the action buttonTapped tries to load a different ViewController.

I get confirmation that the button action worked (the routine was called). The routine is as follows:

func buttonTapped() {
    print("ButtonTapped")

    let myPickerController = self.storyboard?.instantiateViewController(withIdentifier: "picker") as? MyPickerController
    print("1")
    self.present(myPickerController!, animated: true)
    print("2")
}

As you can see from the log, I do see that the routine was called, but I do not see the print values 1 or 2 before the crash. Anyone see what I'm doing wrong?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
ICL1901
  • 7,632
  • 14
  • 90
  • 138
  • 1
    Remember table view cells are reused; not sure if it is wise to add a new button each time. Perhaps have each cell already _have_ a button, and re-configure it each time you dequeue a cell. You can reset all target/actions using `nil` arguments to `removeTarget...` : http://stackoverflow.com/a/3340840/433373 – Nicolas Miari Jun 29 '16 at 06:45
  • Good idea. I'll think I've tried that, but I'll check – ICL1901 Jun 29 '16 at 06:47
  • Hmm. I have set the button as a global variable. I call it for the specific cell that needs it. I can see that the button activates the function, but then I still get the crash.. Other ideas welcome please. – ICL1901 Jun 29 '16 at 07:06
  • Oh, so only one button exists at a time. You said you instantiate it "at the beginning of cellForRowAt", which is called once per cell the table needs to display. Even if there is one button that is reused, make sure you don't add the same target multiple times. – Nicolas Miari Jun 29 '16 at 07:10
  • Oops. I had set it that way, but I took your point and moved creating the button to viewDidLoad. Sorry for confusion – ICL1901 Jun 29 '16 at 07:16
  • If you only need one button at any time, shared among all cells, by all means create it once on setup, add the target/action there, and perhaps change the appearance/label text every time you reuse it (i.e., attach it to a cell). I believe you need to call `removeFromSuperview()` on the button before adding it as child of a different view (cell), otherwise an exception will be thrown by UIKit. – Nicolas Miari Jun 29 '16 at 07:20

1 Answers1

4

Add target like,

 myButton.addTarget(self, action: #selector(YourControllerName.buttonTapped(_:)), for: .touchUpInside)

then change your function like,

 func buttonTapped(sender : UIButton){

 ....
 }

Hope this helps you.

Jigar Tarsariya
  • 3,189
  • 3
  • 14
  • 38