Q:

Clicking button hides keyboard and doesnt hit the action when keyboard is up

I am using the following code to raise the keyboard when I click on a UITextField.
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardDidShow, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

self.hideKeyboardWhenTappedAround()

Here is the extension I am using.
extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }
}

The problem I have having is when the keyboard is up, it puts the one main button (the search button) unclickable. If I click this button, it just lowers the keyboard, then I have to click it again. 
How can this be fixed?

A:

What I did to solve this issue with one of my project was to listen to the gesture recognizer. If the element being actioned is a button I don't perform the action. 
firstly, assign the delegate of your tapGesture recognizer
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false
        tap.delegate = self // assign the delegate to the viewcontroller/who ever you assigned to conform to the UIGestureRecognizerDelegate
        view.addGestureRecognizer(tap)
    }

Conform to UIGestureRecognizerDelegate and use the function shouldReceive touch to decide what action to take. To fix your issue, if a user taps on a button we just don't perform the gesture.

extension UIViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return !(touch.view is UIButton)
    }
}

caveat of this, is that if you do perform the button action instead of the gesture you need to implement/call the dismiss keyboard method after the button performs it process.

