Preloading the UIKeyboard
During the beta testing of Gratuitous, nearly every user reported the same problem. Sometimes, it would take them several touches before the text field would register their touch and bring up the keyboard. Digging into this more revealed that on the first touch of a text field, there would be a noticeable 1-2 second delay before the keyboard appeared. All subsequent touches of any text field resulted in the keyboard appearing immediately.
I examined other apps and confirmed this issue was present there too. Doing some digging online I found others’ apps had the same problem, but no one had a solution. Some worked around the issue by immediately bringing up the keyboard on app load (a la the mint.com app). This is acceptable provided it makes sense to immediately show the keyboard when the app starts. Not so for Gratuitous.
To me, this initial delay during the keyboard load was a completely unacceptable user experience that we had to fix. Left as-is, Gratuitous appeared very sluggish and initially unresponsive. Ick.
Not deterred, I decided to try a little slight of hand with a hidden dummy UITextField and hiding the keyboard on initial load. It turns out this slight of hand works pretty darn good. So good in fact that when you touch a text field in Gratuitous, the keyboard appears immediately; even the very first touch.
First, add a dummy UITextField to your root view controller. We need to make it the first responder on load which will invoke the keyboard. Note that we’re hiding our dummy UITextField and disabling any user interaction with it.
- (void)viewDidLoad { [super viewDidLoad]; dummyKeyboardLoading = YES; dummyTextField.hidden = YES; dummyTextField.userInteractionEnabled = NO; [dummyTextField becomeFirstResponder]; }
Now that our dummy UITextField is loading the keyboard, we need to make the keyboard invisible and disable any user interaction with it before it appears so the user isn’t aware of this initial keyboard load. It is important to note that we maintain a boolean variable, dummyKeyboardLoading, so that we only hide and disable the keyboard on the initial load (and not subsequent loads).
- (void) keyboardWillShow:(NSNotification *) notification { UIWindow *window = nil; UIView *keyboardView = nil; NSArray *windows = [[UIApplication sharedApplication] windows]; for (int i = 0; i < [windows count]; ++i) { window = [windows objectAtIndex:i]; for (int j = 0; j < [window.subviews count]; ++j) { keyboardView = [window.subviews objectAtIndex:j]; if ([[keyboardView description] hasPrefix:@"<UIKeyboard"] == YES) { if (dummyKeyboardLoading) { keyboardView.hidden = YES; keyboardView.userInteractionEnabled = NO; } else { keyboardView.hidden = NO; keyboardView.userInteractionEnabled = YES; } return; } } } }
Finally, once our dummy keyboard has loaded, we need to make it go away by resigning first responder status on the dummy UITextField.
- (void) keyboardDidShow:(NSNotification *) notification { if (dummyKeyboardLoading) { dummyKeyboardLoading = NO; [dummyTextField resignFirstResponder]; } }
And that’s it. In Gratuitous, this hidden preloading of the UIKeyboard is done while the paper is animating up onto the wood grain table when the app starts up. This animation was the perfect spot to conceal the hidden cost of preloading the keyboard as the user is completely unaware. The end result is a very responsive app and a very happy developer.





your blog entry saved me a lot of time! thanks so much for figuring this out. the initial delay on the UIKeyboard was driving me crazy, and you’re right, this does work pretty darn good.
truth be told, at first your solution wasn’t really making that much of a difference for me. but then i realized that the dummy keyboard was the Default keyboard, while my actual keyboard that i present to users is the Alert keyboard. it seemed to work for me when i duplicated my real UITextField as the dummy text field. perhaps the actual size and other characteristics of the text fields need also be the same in order for this keyboard preloader to be effective.
you should report a bug to apple and forward your solution. they might streamline it and hopefully include it in future versions of the SDK.
thanks again!
Darkroom
Montréal, Canada
Darkroom
22 Aug 09 at 4:12 pm
@Darkroom
I’m glad this post was able to help you out!
To be honest, I’m not sure why the UIKeyboard takes so long to load. This hack, while effective, should be completely unnecessary. In fact, with the latest version of our app, Gratuitous, I completed rolled my own custom keypad (for other reasons which I’ll elaborate in an upcoming blog post) and the initial load is perceived as instantaneous. I’m not doing any sort of preloading of this custom keyboard; rather, I’m just loading it from the xib as you normally for a view.
As for a bug report, I did log one to Apple when I first dealt with this issue.
kevin
22 Aug 09 at 4:42 pm
Thanks, I’ve been struggling with the same issue myself. Althought I wonder if this solution might get the app rejected for using undocumented apis
danny
25 Oct 09 at 8:15 pm
@danny
This solution isn’t using any undocumented APIs so it shouldn’t be at risk for rejection by Apple. However, this solution does rely on the class name of the stock keyboard so if Apple decided to change that then this code would no longer work.
Something I just thought of but it may be possible to modify this solution such that instead of looping for the first view named UIKeyboard you could instead check to see if the view equals the reference of the dummy keyboard. If this works, it would make this solution more robust.
kevin
25 Oct 09 at 9:07 pm
Thanks for the tip, it worked great. My client wasn’t happy with the initial keyboard delay, and neither was I. Strange that Apple haven’t addressed it.
I simplified the solution by using the existing UITextField rather than creating a dummy/hidden one.
Chris Miles
26 Oct 09 at 11:20 pm
Thank you! This is very practical blog post. I had my application and it was almost done, worked great. Just the small cosmetic issue – the first keyboard loading took too much time, which was not desired since it was a social app requiring quick comment posting. This how-to solved this problem.
Petr Dvorak
26 Mar 10 at 8:36 am
[...] This post was mentioned on Twitter by Dave Mitchell, Tak Fung. Tak Fung said: For iPhone devs who want to preload the keyboard so it appears quickly – this is useful: http://tinyurl.com/ykdxptf [...]
Tweets that mention Preloading the UIKeyboard at Uproar Blog -- Topsy.com
29 Mar 10 at 9:58 am
I’ve put in several layers of “subviews” in your code, and not once has one come up with the “UIkeyboard”?
the keyboard is coming up, and dismissing, but you can see it come up at launch of the app… so i went in to see if that subview code was working, and basically none of the subviews are the UIkeyboard?
anyone have any ideas why i can’t see this subview? (using latest iphone beta as of this date)
jonk
15 May 10 at 9:30 am
@jonk: we haven’t tested this technique in the 4.0 beta. Do you have it working in 3.x?
rick
20 May 10 at 11:12 am
jonk,
In the latest betas there’s an extra container view, probably used to manage pixel doubling. Add in another for loop, and you’ll find the keyboard.
The name remains the same UIKeyboard, luckily…
best wishes, thanks for the post Kevin!
A Developer
4 Jun 10 at 4:36 pm
Hi, Thanks for your example but I can get it working with iOS 4.0. Any ideas why?
Matt
20 Jun 10 at 1:06 am
@Matt — see “A Developer’s” comment above on the addition of an extra container view under iOS 4.0
kevin
21 Jun 10 at 8:14 am
Unfortunately, the trick does not work in iOS 4 anymore, because the UIKeyboard view is not available at UIKeyboardWillShowNotification but on the next run loop pass. You can access it to hide it, for example using performSelector: afterDelay:0, but then the keyboard is already visible, so it’s too late… I’ll try to find another solution and I count on You all too
kamilk
28 Jun 10 at 6:16 am