UIViewController's canPerformAction is called multiple times with the same action and sender

135 Views Asked by At

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
1

There are 1 best solutions below

0
Milan Savaliya M On

Button Target can not be nil

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

enter image description here