0

I have a table view cell with a button like such

    let downButton: UIButton = {
      let button = UIButton()
      button.translatesAutoresizingMaskIntoConstraints = false
      button.addTarget(self, action: #selector(exe), for: .touchUpInside)
      return button
    }()

@objc func exe(product: Product) {
    print("AEADSFADSF")
}

The button is added as a subview and displayed correctly but it doesn't execute the function added to it's target. If I have a function named exe on the Table View Controller, it executes. How can I make this work? I need the function to take a product as a parameter.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • How is the `downButton` added to some view? And note that the `exe` function can't have a parameter of type `Product`. The only parameter it can have is the `UIButton` that triggered it. – rmaddy Dec 12 '18 at 18:25

2 Answers2

0

You should change you exe(product:) function to:

@objc func exe() {
   print("AEADSFADSF")
}

If you want to detect which button was pressed in a table view, you can use a method described in detecting uibutton pressed in tableview: Swift Best Practices

Maciej Gad
  • 1,701
  • 16
  • 21
  • problem is, the function itself is not executed. No matter the parameters. – Luiz Fernando França Dec 12 '18 at 17:02
  • Parameters matter! `#selector(exe)` means that your function will be defined as `@objc func exe() `. You can't have `product: Product` parameter and call it as an action for UIButton. Maybe this question will help you: https://stackoverflow.com/questions/27429652/detecting-uibutton-pressed-in-tableview-swift-best-practices – Maciej Gad Dec 12 '18 at 17:08
  • 1
    @bazyl87 You are incorrect. The use of `#selector(exe)` means that the `exe` function can either have no parameter, a named parameter, or an anonymous parameter. The OP's code is wrong in other ways since the `exe` function must have either no parameter or a `UIButton` parameter. But either way, the `#selector(exe)` will work. That's not the issue. – rmaddy Dec 12 '18 at 18:27
  • @rmaddy you are right. I've always used `#selector(exe(parameter:))` syntax and wasn't aware that you can use only `#selector(exe)`. That is more strange because it should call `exe(product: Product)` function but with `UIButton` as `product`, and have a runtime crash when trying to use some of `product` properties. – Maciej Gad Dec 12 '18 at 18:58
0

I think the problem is that self in your addTarget function does not point to the surrounding instance but the closure itself. Try and make your button a lazy var:

lazy var downButton: UIButton = {
    let button = UIButton()
    button.translatesAutoresizingMaskIntoConstraints = false
    button.addTarget(self, action: #selector(exe), for: .touchUpInside)
    return button
}()

"Proof":

let downButton: UIButton = {
    ...
    print(self)
    ...
}()

Prints: (Function)

lazy var downButton: UIButton = {
    ...
    print(self)
    ...
}()

Prints: <ScreenSize.ViewController: 0x7fc0cf4060f0>

André Slotta
  • 13,774
  • 2
  • 22
  • 34