iOS: How to access the `UIKeyboard`?

别说谁变了你拦得住时间么 提交于 2019-11-27 23:10:58

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;
        }
    }
}   

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?

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.

Be aware, Apple has made it clear that applications which modify private view hierarchies without explicit approval beforehand will be rejected. Take a look in the Apple Developer Forums for various developers' experience on the issue.

If you're just trying to disable the keyboard (prevent it from receiving touches), you might try adding a transparent UIView that is the full size of the screen for the current orientation. If you add it as a subview of the main window, it might work. Apple hasn't made any public method of disabling the keyboard that I'm aware of - you might want to use one of your support incidents with Apple, maybe they will let you in on the solution.

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

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!