Closing iOS Keyboard by Touch: Anti-patterns and 3 Working Solutions in Swift

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why doesn't the keyboard close by itself?

\n

Hello, fellow developer! If you've ever written a login form, search bar, or messenger on iOS, you've probably encountered this situation: the user has entered text, but the keyboard stubbornly stays on the screen. The "Done" button wasn't pressed, the user taps an empty space, but nothing happens. A classic.

\n\n

This is one of the most popular topics on Stack Overflow, where the question "Close iOS Keyboard by touching anywhere using Swift" has thousands of views. The problem isn't that it's difficult to do. The problem is that beginners (and not only) often choose incorrect or "dirty" methods. Let's break down the top 3 mistakes, and then look at three correct, working solutions.

\n\n

Today we're talking about Swift and UIKit. If you use SwiftUI — take a look too, the principles are similar.

\n\n

Mistake #1: "Adding TapGesture to everything"

\n

The most common mistake is adding a UITapGestureRecognizer to a UIView, but forgetting to disable cancelsTouchesInView. As a result, buttons and tables stop responding to taps. The user taps the "Send" button, but the keyboard dismissal triggers instead of form submission.

\n\n

Example of incorrect code:

\n
override func viewDidLoad() {\n    super.viewDidLoad()\n    let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))\n    view.addGestureRecognizer(tap)\n}\n\n@objc func dismissKeyboard() {\n    view.endEditing(true)\n}
\n\n

At first glance — it looks fine. But in practice, if you have a UITableView or UIButton, their taps can be "swallowed" by this gesture. This is especially noticeable when you add such a gesture to a scrollView.

\n\n

How to fix:

\n

Add the line tap.cancelsTouchesInView = false. This will allow other interface elements to receive touch events.

\n\n
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))\ntap.cancelsTouchesInView = false\nview.addGestureRecognizer(tap)
\n\n

But even this is not an ideal solution if you have a complex interface.

\n\n

Mistake #2: "Tapping empty space breaks the table"

\n

The second popular problem is incorrect interaction with UIScrollView or UITableView. If you add a UITapGestureRecognizer to a view that contains a table, tapping a cell might trigger both the gesture and the didSelectRow method simultaneously. Or, even worse, the gesture will intercept the touch, and the cell won't be highlighted.

\n\n

Solution: use UIGestureRecognizerDelegate

\n

Implement the gestureRecognizer(_:shouldReceive:) method and check whether the tap was on a text field or another element. If the touch landed on a UITextField or UITextView — don't block the gesture.

\n\n
extension ViewController: UIGestureRecognizerDelegate {\n    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {\n        // Don't intercept touches if they landed on a text field\n        if touch.view is UITextField || touch.view is UITextView {\n            return false\n        }\n        return true\n    }\n}
\n\n

Now the gesture will only trigger when tapping empty areas, while text fields remain interactive.

\n\n

Mistake #3: "Forgetting about the keyboard return key"

\n

Many developers implement dismissal by tap, but forget about the "Return" (Enter) button on the keyboard. The user might press "Done" and expect the keyboard to close. If this isn't handled — you'll get a negative UX.

\n\n

How to fix:

\n

Conform to the UITextFieldDelegate protocol and implement the textFieldShouldReturn method:

\n\n
class View                

Blogs

Book Recommendations