Keyboard Handling in iOS — Swift 5
This article was originally published at CometChat.
“Handling Keyboard in iOS” — This has been a topic or rather a problem since the inception of iOS Development. Whether you are a beginner developer or an experienced one, you’ll always be dealing with the handling of keyboards in your apps! But there’s not just 1 issue with the keyboard that we are talking about here. We have to manually handle a couple of issues. Here, let me show you exactly what I mean -
Manually handle the dismissal of the keyboard
When you tap on a text-field, the keyboard pops up and allows you to type in whatever you want. Now once you are done writing, there is no default done button which will 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 now!” Sure thing boss! If that’s the protocol, we will follow.
Moving text-fields on your screen when the Keyboard appears & disappears
When your text-field is placed in the lower area of your screen like for example a chat application, you’ll come across this scenario — You tap on it and the keyboard appears and 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 sure appears, but now your text-field is no longer visible! The keyboard just 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 a beginner in iOS development, this issue caught me by surprise! Mainly because I code in Android too and this behavior is handled very gracefully by default over there. Never knew something as simple as a keyboard would have to be handled manually.
Enough of complaints. Where there is a problem, there ought to be a solution. Our jobs as engineers and developers are 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. For now, I’ll be walking you through the findings and solutions that I use in my day to day projects.
Problem 1 — Handling Keyboard dismissal (How do I make this Keyboard go away?)
Like we were discussing above, keyboards in iOS don’t disappear on its own. The return key on the keyboard does nothing by default! Also, there is no return key for Numeric Keypad! Tapping outside the keyboard area also does not make that thing go away! Whhattt???
Unfortunately, Apple has not yet made the dismissal of the keyboard a default thing. Hence we developers need to handle this scenario programmatically in our app. Fortunately, there are several ways in which we can achieve this functionality and that too within a few lines of code. Which way to implement in your code may depend on your exact scenario. You can judge the best one and use the same as per your requirement.
Via Tap Gesture -
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 docs say the below 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 keyboard appears, just tap outside anywhere on the view and your keyboard would be dismissed.
The below code can be shortened into just 2 lines but I have specifically broken into functions to help make this clear as possible. I have also added comments in the code to help understand what each function does.
Via Keyboard Return Key -
Another great option is to use that non-functional keyboard Return/Done/Continue key. It’s just sitting there doing nothing unless we have specified some custom behavior in textFieldShouldReturn function.
textFieldShouldReturn Asks the delegate if the text field should process the pressing of the return button.
- Here you would first have to set the delegates for the text-fields.
- Set Tag to the text-fields. What is a Tag, you ask? Apple documentation says — An integer that you can use to identify view objects in your application. The setting of Tag is optional and would not be required when you have only 1 text-field. But here I am assigning Tag to the text-fields by incrementing their value by 1 and in the order, they are placed on the screen. This would help us identify the text-fields in code.
- textFieldShouldReturn fires when the user presses the Return key on the keyboard. Hence, here we check — Is there any other text-field in the view whose tag is +1 greater than the current text-field on which the return key was pressed. If yes → then move the cursor to that next text-field. If No → Dismiss the keyboard
Also don’t worry about that password field not visible when typing. We’ll solve that issue when we discuss about moving text-fields to visibility as per the keyboard in the later section of this article.
Via Toolbar for Number Pad -
The above solution with textFieldShouldReturn works great but unfortunately, there is no “Return” key on iOS Number Pad. To overcome our barrier here in the case of Number Pad, we can add a simple Toolbar above our Keyboard with a “Done” button. This “Done” button is going to call the same function we used in our Tap Gesture Method above and would dismiss our keyboard. To keep consistency across the fields, you can use Toolbars across the app as a common patter to dismiss your keyboard.
I found a nice article about extension for creating Done Button Toolbar which will help you reduce the code duplication and hook the same function across the app -
If you need more insights & ways on dealing with Keyboard dismissal, I found this great article on medium, You can find it here -
Problem 2 — Moving text-fields as per the keyboard (Where is my text-field?)
We need to see our text while typing, that’s basic UX. Unfortunately, when your text-field is placed at the bottom area of your screen like for example in a chat application, your keyboard is going to overlap it as soon as you tap on the field. We need to handle this programmatically beforehand.
What is our expected behavior here?
First, we need to check whenever a field is tapped and the keyboard appears, whether the keyboard is going to overlap the field (which in our chat application’s case, it will)? If so → scroll the view such that your text-field appears just above the keyboard. If your text-field is not overlapped by the keyboard, then there is no need to shift/scroll the screen.
Enough about the problem, let’s take a deep dive into the solution. I have added comments in the below code to help in better understanding the role of each function in achieving our desired goal.
Problem 3 — Repetition of code
We would most probably have multiple text-field in our Applications. And these text-fields would be scattered across our entire application on different Screens. The above solution we implemented was in single ViewController. So how do we go about implementing these solutions in all the ViewControllers wherever we need to handle our Keyboard?
The first thing that would come to our minds is to add the above code snippets in all the ViewControllers wherever we need to handle such scenarios. But that means we would have to keep manually adding this code in every ViewController. There has to be a better way!
Thankfully, there is! We would be using some basic concept of OOP over here — Inheritance. We would be declaring a base keyboard handling class which would be inherited from our default UIViewController. Now wherever we need to handle our keyboard, we would just inherit our class from our base class.
- Declare a base class for handling keyboard
- Write our entire keyboard handling code in that base class
- Inherit your ViewControllers from this base class and Voila! You have handled your keyboard issues elegantly.
We’ll see how this looks in code -
Bonus — Let’s see some Libraries
So let’s say you don’t want to handle any of the issues mentioned above manually. There may be various reasons for that but yeah the possibility exists. It’s fine, sometimes time is of great essence. Don’t worry, we have got that aspect also covered in this article. There are various libraries out there that solve the Keyboard Dismissal and TextField handling problem. I’ll list down a couple so that you can go through their read-me and find for yourself whichever suits your needs.
So far we explored the problem of keyboard dismissal & TextField handling with keyboard. We also explored some of the ways in which we can easily solve these problems along with avoiding code repetition in our project. There is no such good or bad way when it comes to solving a technical problem. What matters the most is — At that particular moment, what works for you? what works for the project? what works for your team? There may be times when you would 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 :)
That’s all from this article, do share if you all have any other ideas & approaches to solve this particular problem. I would be happy to discuss the same!
If you enjoyed reading this article and learned something, share it amongst your developer friends/colleagues and spread the knowledge! If you have anything to discuss regarding Keyboard Handling or any other topic related to Mobile Apps, Development, Designing, Engineering… Drop a comment below or DM me on Twitter :)
If you find this interesting, chances are you’ll find my twitter feed too! I keep sharing articles and stuff related to development, design and productivity on a daily basis. So hop on, follow me on Twitter and enjoy the learning ride!
Till the next Article…