Search code examples
swiftuigesturerecognizerselectoraddtarget

Different behavior between addTarget and addGestureRecognizer


I have a function that creates a button with a selector function as a target. The address of a button gets passed to handleSelectPhoto.

lazy var image1Button = createButton(selector: #selector(handleSelectPhoto))
func createButton(selector: Selector) -> UIButton {
    let button = UIButton(type: .system)
    button.addTarget(self, action: selector, for: .touchUpInside)
    return button
}
@objc func handleSelectPhoto(button: UIButton) {
    // Do something with button, this works
}

Now, I am trying to change the class of the above from UIButton to UIImageView like the following,

lazy var image1Button = createButton(selector: #selector(handleSelectPhoto))
func createButton(selector: Selector) -> UIImageView {
    let view = UIImageView()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: selector))
    view.isUserInteractionEnabled = true
    return view
}
@objc func handleSelectPhoto(button: UIImageView) {
    // HERE, button does not get passed
}

With the above changes, in handleSelectPhoto, button instance is not correct. I can not read it as UIImageView type.

If I add a selector function using addGestureRecognizer, does it behave differently than adding a selector function using addTarget, in terms of how selector function is executed with parameters? Maybe I am not understanding how this selector function works...


Solution

  • You should make your tell while setting the selection that your function will accept a parameter by adding : at the end of method name.

    lazy var image1Button = createButton(selector: #selector(handleSelectPhoto:))
    

    UIKit will automatically understand that the selector methods parameter will be of type UITapGestureRecognizer. Now rewrite the below method like this and you will be good to go.

    @objc func handleSelectPhoto(gesture: UITapGestureRecognizer) {
            if let buttonImageView = gesture.view as? UIImageView {
                //Here you can make changes in imageview what ever you want.
            }
    }