Handling keyboards in iOS has always been a problem. Whether you are a beginner or an experienced developer, you'll always need to handle keyboards in your apps and chat applications sure won't exist without text-fields! But, there's not just one issue with the keyboard; you have to manually handle a couple of issues, let me show you what I mean:
When you tap on a text-field, the keyboard pops up and allows you to type whatever you want. Once you are done writing, there is no default ‘done’ button to dismiss the keyboard, tapping outside the keyboard ain't gonna do anything either. It's like iOS saying - "Isn't it enough I popped up the keyboard automatically for you? Figure out a way to make it go away on your own" Sure thing boss! If that's the protocol, we will follow.
When building chat applications, another common scenario is to place the text-field at the bottom of the screen. You tap on the input and the keyboard appears, your text-field should move upwards, along with the keyboard. This does not happen by default on iOS. What happens is - when you tap on the text-field, the keyboard appears, but your text-field is no longer visible. The keyboard overlaps the text-field on the screen that was placed near the bottom of the screen. Yes, you heard it right, iOS won't automatically shift the text-field as per the keyboard.
When I was new to iOS development, this issue caught me by surprise. But, enough complaints. Where there is a problem, there ought to be a solution. Our job as engineers and developers is to find answers to problems like this and solve them elegantly. There are a lot of ways in which people have already solved this problem. I'll walk you through the findings and solutions that I use in my projects.
Problem 1 - Handling Keyboard dismissal (How do I make this Keyboard go away?)
Keyboards in iOS don’t disappear on their own. The return key does nothing by default and there is no return key for the Numeric Keypad. Tapping outside the keyboard area also does not make that thing go away.
Unfortunately, Apple has not yet made the dismissal of the keyboard a default behaviour. Hence, we developers need to handle this scenario programmatically in our app. Fortunately, there are several ways in which we can add this functionality. Which method to implement in your code may depend on your specific scenario. You can judge the best one for yourself..
This is the quickest way to implement keyboard dismissal. Just set a Tap gesture on the main View and hook that gesture with a function which calls view.endEditing().
Apple’s docs have this to say about endEditing():
“Causes the view (or one of its embedded text fields) to resign the first responder status.”
That’s it. Now when you tap on a text-field and the keyboard appears, just tap outside, anywhere on the view, and the keyboard will be dismissed.
The code below can be shortened into just 2 lines but I have specifically broken it into functions to help make the example as clear as possible. I have also added comments to help you understand what each function does.
Keyboard ‘Return’ Key
Another great option is to use the keyboard's Return/Done/Continue key by specifying some custom behavior with the textFieldShouldReturn() function.
textFieldShouldReturn() Asks the delegate if the text field should process the pressing of the return button. In order to use this method you need implement the following behaviour:
Set the delegates for the text-fields.
Set a Tag on the text-fields. A Tag is “An integer that you can use to identify view objects in your application.” The setting of Tag is optional and not required if there is only 1 text-field. In this example I am assigning a Tag to the text-fields by incrementing their value by 1 in the order they are placed on the screen. This helps to identify the text-fields in code.
textFieldShouldReturn() fires when the user presses the Return key on the keyboard.
If there is any other text-field in the view (where the fields tag is greater than the current fields) move the cursor to that next text-field. If not dismiss the keyboard
This is demonstrated in the following code:
Toolbar for Number Pad
The above solution works great for text fields, unfortunately there is no “Return” key on the iOS Number Pad so you need another solution. In the cases where the Number Pad is displayed, you can add a simple Toolbar above the Keyboard with a “Done” button. The “Done” button will call the same function used in the Tap Gesture Method in order to dismiss the keyboard. To be consistent you could use toolbars across the app as a common pattern to dismiss the keyboard regardless of input type.
Here is an extension for creating a Done Button Toolbar which will help you reduce code duplication and hook the same function across the app -
If you need more insight or are interested in different techniques you should read this article Best way to dismiss Keyboard in a View Controller iOS (Swift)
Problem 2 - Moving text-fields as per the keyboard (Where is my text-field?)
We need to see the text while typing, that's basic UX. Unfortunately, when your text field is placed at the bottom of the screen like in our chat application, the keyboard is going to overlap it as soon as you tap on the input field. We need to handle this programmatically beforehand.
First, you need to check whenever a field is tapped and the keyboard appears, if the keyboard is going to overlap the field or not? If so, scroll the view so that the text-field appears above the keyboard. If the text-field is not overlapped by the keyboard, then there is no need to shift/scroll the screen.
I’ve added comments in the below code to help better understand the role of each function in achieving the desired goal.
Problem 3 - Repetition of code
Most applications don’t have a single text field and these fields are usually scattered across the entire application on different screens. The solutions above were implemented in a single ViewController. The challenge is to implement these solutions in all the ViewControllers wherever there is a need to handle the keyboard.
The first idea that comes to mind is to add the above code snippets to all the ViewControllers in the application
A better solution would be to use inheritance by declaring a base keyboard class which would be inherited from our default UIViewController. Wherever you need to handle the keyboard, you inherit this class from your base class.
You can see an example of this is the code below:
If you don't want to handle any of the issues mentioned above manually there are various libraries that solve the Keyboard Dismissal and TextField handling problems for you. These include:
We explored the problem of keyboard dismissal & TextField handling with the iOS keyboard. We also explored some of the ways in which you can easily solve these problems and avoid code repetition. There is no right or wrong way when it comes to solving these problems, what matters most is - what works for you, what works for the project, and what works for your team? There may be times when you may need to use a mix of the above techniques or sometimes one single pattern can be followed across the app! At the end of the day what matters is that you solved the problem.