iosswifttarget-action

Target-Action parameter issue in Swift


I am following an iOS dev tutorial and reading their code. First Code:

override func viewDidLoad() {
    super.viewDidLoad()

    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
    gestureRecognizer.cancelsTouchesInView = false
    tableView.addGestureRecognizer(gestureRecognizer)
}

Second Code:

@objc func hideKeyboard(_ gestureRecognizer: UIGestureRecognizer) {
    let point = gestureRecognizer.location(in: tableView)
    let indexPath = tableView.indexPathForRow(at: point)
    if indexPath != nil && indexPath!.section == 0 && indexPath!.row == 0 {
        return
    }
    descriptionTextView.resignFirstResponder()
}

From what I understand, the first code enables keyboard disappeared when user tap anywhere on the screen. To implement this, Target-Action pattern is hired.

In the first code, #selector(hideKeyboard), hideKeyboard doesn't seems to have any parameter. So why there is a parameter in the helper function (second code).

If the parameter is valid, why is gestureRecognizer: UIGestureRecognizer?
I don't quite understand how does the parameter passing work?


Solution

  • A UIGestureRecognizer always passes itself as the parameter to the action handler method. It is fine to use UIGestureRecognizer instead of UITapGestureRecognizer in the handler routine since UIGestureRecognizer is a superclass of UITapGestureRecognizer, but what is passed in this case is actually the UITapGestureRecognizer instance.

    If this handler routine isn't used by other UIGestureRecognizers, I would write it like this:

    @objc func hideKeyboard(_ gestureRecognizer: UITapGestureRecognizer) {
    

    This allows you to access properties of UITapGestureRecognizer that aren't common with the superclass.

    The selector syntax is just using a shortcut syntax which is sufficient in this case to identify the method. It could have used #selector(hideKeyboard(_:)) to indicate that there is a parameter, but it isn't necessary.

    Note that the parameter to the handler routine has to be the gesture recognizer. You can't substitute another type, but you can leave the parameter off altogether in the handler routine if you don't need access to the gesture recognizer.