Archive for March, 2009
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.




