iOS: How to access the `UIKeyboard`?
Solution 1
How about using -[UIApplication beginIgnoringInteractionEvents]
?
Also, another trick to get the view containing the keyboard is to initialize a dummy view with CGRectZero
and set it as the inputAccessoryView
of your UITextField
or UITextView
. Then, get its superview
. Still, such shenanigans is private/undocumented, but I've heard of apps doing that and getting accepted anyhow. I mean, how else would Instagram be able to make their comment keyboard interactive (dismiss on swipe) like the Messages keyboard?
Solution 2
Try this:
// my func
- (void) findKeyboard {
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIKeyboard.
UIView *foundKeyboard = nil;
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
}
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
foundKeyboard = possibleKeyboard;
break;
}
}
}
Solution 3
I found that developerdoug's answer wasn't working on iOS 7, but by modifying things slightly I managed to get access to what I needed. Here's the code I used:
-(UIView*)findKeyboard
{
UIView *keyboard = nil;
for (UIWindow* window in [UIApplication sharedApplication].windows)
{
for (UIView *possibleKeyboard in window.subviews)
{
if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"])
{
keyboard = possibleKeyboard;
break;
}
}
}
return keyboard;
}
From what I could make out, in iOS 7 the keyboard is composed of a UIPeripheralHostView
containing two subviews: a UIKBInputBackdropView
(which provides the blur effect on whatever's underneath the keyboard) and a UIKeyboardAutomatic
(which provides the character keys). Manipulating the UIPeripheralHostView
seems to be equivalent to manipulating the entire keyboard.
Discaimer: I have no idea whether Apple will accept an app that uses this technique, nor whether it will still work in future SDKs.
Solution 4
Under iOS 8 it appears you have to jump down the chain more than in the past. The following works for me to get the keyboard, although with custom keyboards available and such I wouldn't rely on this working unless you're running in a controlled environment.
- (UIView *)findKeyboard {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
UIView *inputSetContainer = [self viewWithPrefix:@"<UIInputSetContainerView" inView:window];
if (inputSetContainer) {
UIView *inputSetHost = [self viewWithPrefix:@"<UIInputSetHostView" inView:inputSetContainer];
if (inputSetHost) {
UIView *kbinputbackdrop = [self viewWithPrefix:@"<_UIKBCompatInput" inView:inputSetHost];
if (kbinputbackdrop) {
UIView *theKeyboard = [self viewWithPrefix:@"<UIKeyboard" inView:kbinputbackdrop];
return theKeyboard;
}
}
}
}
return nil;
}
- (UIView *)viewWithPrefix:(NSString *)prefix inView:(UIView *)view {
for (UIView *subview in view.subviews) {
if ([[subview description] hasPrefix:prefix]) {
return subview;
}
}
return nil;
}
Solution 5
For an app I am currently developing I am using a really quick and easy method:
Add this in the header file:
// Add in interface
UIWindow * _window;
// Add as property
@property (strong, nonatomic) IBOutlet UIView * _keyboard;
Then add this code in the bottom of the keyboardWillShow function:
-(void) keyboardWillShow: (NSNotification *) notification {
.... // other keyboard will show code //
_window = [UIApplication sharedApplication].windows.lastObject;
[NSTimer scheduledTimerWithTimeInterval:0.05
target:self
selector:@selector(allocateKeyboard)
userInfo:nil
repeats:NO];
}
This code look for when the keyboard is raised and then allocates the current window. I have then added a timer to allocate the keyboard as there were some issues when allocated immediately.
- (void)allocateKeyboard {
if (!_keyboard) {
if (_window.subviews.count) {
// The keyboard is always the 0th subview
_keyboard = _window.subviews[0];
}
}
}
We now have the keyboard allocated which gives you direct "access" to the keyboard as the question asks.
Hope this helps
ma11hew28
Updated on June 25, 2022Comments
-
ma11hew28 almost 2 years
I want to get a pointer reference to
UIKeyboard *keyboard
to the keyboard on screen so that I can add a transparent subview to it, covering it completely, to achieve the effect of disabling theUIKeyboard
without hiding it.In doing this, can I assume that there's only one
UIKeyboard
on the screen at a time? I.e., is it a singleton? Where's the method[UIKeyboard sharedInstance]
. Brownie points if you implement that method via a category. Or, even more brownie points if you convince me why it's a bad idea to assume only one keyboard and give me a better solution. -
ma11hew28 almost 13 yearsOK. Is there a way to disable the keyboard without hiding it?
-
RyanR almost 13 yearsAre you trying to prevent the keyboard from showing up when a user taps in a text field?
-
ma11hew28 almost 13 yearsNo, I want to disable it during an animation. Apple's Passcode Lock feature does this when you're setting a passcode.
-
aksommerville over 11 yearsThe keyboard is in a separate window, so a fullscreen view to block it will not work (if you're adding it to your main window). Check [[UIApplication sharedApplication] windows].
-
The iCoder over 10 yearsFor generic coding please replace if condition of for loop by if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) { for (__strong UIView *anotherPossibleKeyboard in [possibleKeyboard subviews]) { if ([[anotherPossibleKeyboard description] hasPrefix:@"<UIKeyboard"]) { foundKeyboard = anotherPossibleKeyboard; break; } } }
-
Martin Stolz almost 10 yearsThanks. But I would use a slightly different check for the keyboard:
Class keyboardClass = NSClassFromString(@"UIPeripheralHostView"); if ([possibleKeyboard isKindOfClass:keyboardClass])
. Instead of relying on a string description. Should also be a bit more performant. -
mihai over 9 yearsgreat suggestion. it works well in 7.1. How can i find the keyboard when its off screen? or is it destroyed and doesnt exist?
-
matteok over 7 yearswill this prevent app store approval?
-
alparsons over 7 years@matteok This alone - I don't think so. Whatever you plan to do with the keyboard though probably would. I used it for specific enterprise reasons.
-
matteok over 7 yearsWhat if you apply a transform to the keyboard-window during a transition?
-
meaning-matters over 7 yearsHow can
beginIgnoringInteractionEvents
be used?