April 26, 2020

Dismiss Keyboard with Swift in iOS app

Dismiss Keyboard with Swift in iOS app

Dismissing the keyboard in iOS is something that almost every app will need to do at some point if it has a UITextField or UITextView.

In this tutorial I will go through a few techniques that you can use to dismiss the keyboard in your app. Some techniques are better than others, but it depends on your use case.

Dismiss keyboard with Return key

In order to use the return key, we need to adopt the UITextFieldDelegate which requires us to set the delegate of each text field that we use in our view. This to me feels dirty but there are ways that one can clean it up.

NOTE: This will not work on a UITextView because we are using the UITextFieldDelegate and the UITextViewDelegate does not have this functionality.

So let's see how this can be used. For this technique I am going to assume that you already have a text field setup.

Before we can add the delegate method to our view controller, we need to adopt the UITextFieldDelegate. This is what my ViewController declaration looks like with the UITextFieldDelegate:

class ViewController: UIViewController, UITextFieldDelegate {
	// Contents of ViewController
}

Let's implement the textFieldShouldReturn delegate method:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}

Now that we have conformed to UITextFieldDelegate and implemented the textFieldShouldReturn method. We can set the text field's delegate property to self.

For me this will look like this:

textfield.delegate = self

Now if you run your app, the return key should dismiss the keyboard.

Dismiss keyboard with Tap

There are two techniques that we will go through that will hide the keyboard using a tap. The first technique is not a way that I would ever use due to limitations which I discuss after the code example.

Using touchesBegan

As I mentioned, this is not a way that I would really use because it doesn't work in quite a few important situations. That doesn't mean that there are no uses cases for it, but I would choose a different way.

Anyway, let's get to the code:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches,
                       with: event)
    self.view.endEditing(true)
}

Now, this does the job in some situations but after testing it, it fails in two important situations. If you have a button in your app and you tap it, this function will not be called. The same issue applies to a UITableView, which makes sense given the following quote from Apple:

UIKit calls this method when a new touch is detected in a view or window. Many UIKit classes override this method and use it to handle the corresponding touch events.

Using a Tap gesture

This is my favourite way to dismiss a keyboard. From my testing, this works when you tap a button, it works with table views, it works when tapping on the view controller's view. So this is my go to way of doing this, it is quite easy as well.

This is the code that I have when I create the tap gesture and add it to my view.

let tapGesture = UITapGestureRecognizer(target: self,
                                        action: #selector(hideKeyboard))
tapGesture.cancelsTouchesInView = false
self.view.addGestureRecognizer(tapGesture)

This still needs a function to call, so I have created the following one:

@objc
private func hideKeyboard() {
    self.view.endEditing(true)
}

And that is it, this works in most of the situations that I have tried out and it is simple. This can also be used to create an extension for UIViewController so that you have access to this in all view controllers.

Dismiss keyboard with Scroll

If you are working with a UITableView, UIScrollView or UICollectionView there is another way to dismiss the keyboard by using a property on one of these classes.

That property is called keyboardDismissMode. Below I have attached my table view code, the last line is where I use this property:

let tableview = UITableView(frame: self.view.bounds)
tableview.delegate = self
tableview.dataSource = self
tableview.keyboardDismissMode = .onDrag

It doesn't matter if you drag up or down, this will hide the keyboard. This could potentially be useful if you have some kind of form and the user needs to scroll to the fields. I am sure there are a few more situations where this would be a useful solution.

Conclusion

There are few ways to dismiss the keyboard in your app. I have not added all of them, for eg, you could add a keyboard accessory view with a button that will allow the user to dismiss the keyboard, but the techniques in this post will work well, and as I mentioned in the post, I personally prefer using the tap gesture because it works consistently and it can be moved into an extension to make it even easier to use.

If you want the full source code for this project, you can find it here.