0

I'm trying to understand in depth how UIResponder actually works under the hood. But there's one thing that I don't catch. Why canPerformAction invokes multiple times even after returning true.

p.s. I pass nil here on purpose

button.addTarget(nil, action: #selector(onButtonTap), for: .touchUpInside)
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton()
        button.setTitle("ACTION", for: .normal)
        button.backgroundColor = .red
        button.addTarget(nil, action: #selector(onButtonTap), for: .touchUpInside)

        view.addSubview(button)

        button.frame = CGRect(x: 200, y: 150, width: 170, height: 50)
    }

    @objc func onButtonTap() {
        print("ACTION")
    }

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        let can = super.canPerformAction(action, withSender: sender)
        print("CAN PERFORM ACTION \(action) = \(can); Sender: \(sender)")
        return can
    }
}
CAN PERFORM ACTION _prepareForTapGesture: = false; Sender: Optional(<UIButton: 0x7f966ef12fa0; frame = (200 150; 170 50); opaque = NO; layer = <CALayer: 0x6000020b0180>>)
CAN PERFORM ACTION onButtonTap = true; Sender: Optional(<UIButton: 0x7f966ef12fa0; frame = (200 150; 170 50); opaque = NO; layer = <CALayer: 0x6000020b0180>>)
CAN PERFORM ACTION onButtonTap = true; Sender: Optional(<UIButton: 0x7f966ef12fa0; frame = (200 150; 170 50); opaque = NO; layer = <CALayer: 0x6000020b0180>>)
CAN PERFORM ACTION onButtonTap = true; Sender: Optional(<UIButton: 0x7f966ef12fa0; frame = (200 150; 170 50); opaque = NO; layer = <CALayer: 0x6000020b0180>>)
ACTION
Nikita Ermolenko
  • 2,139
  • 2
  • 19
  • 41

1 Answers1

0

Button Target can not be nil

button.addTarget(self, action: #selector(onButtonTap), for: .touchUpInside)

enter image description here