IOS: Как получить доступ к `UIKeyboard`?

Я хочу получить ссылку на указатель на UIKeyboard *keyboard на клавиатуре на экране, чтобы я мог добавить к ней прозрачный субвью, полностью покрыв его, чтобы добиться эффекта отключения UIKeyboard, не скрывая его.

При этом я могу предположить, что на экране есть только один UIKeyboard? I.e., это одноэлемент? Где метод [UIKeyboard sharedInstance]. Брауни указывает, если вы реализуете этот метод через категорию. Или, еще больше пунктов коричневого цвета, если вы убедите меня, почему это плохая идея, чтобы принять только одну клавиатуру и дать мне лучшее решение.

Ответ 1

Как насчет использования -[UIApplication beginIgnoringInteractionEvents]?

Кроме того, еще один трюк, чтобы получить представление, содержащее клавиатуру, - это инициализировать фиктивный вид с помощью CGRectZero и установить его как inputAccessoryView вашего UITextField или UITextView. Затем получим его superview. Тем не менее, такие махинации являются частными/недокументированными, но я слышал о том, что приложения делают это и все равно принимают. Я имею в виду, как еще Instagram сможет сделать свою клавиатуру комментариев интерактивной (увольнять по экрану), как клавиатура Messages?

Ответ 2

Попробуйте следующее:

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

Ответ 3

Я обнаружил, что ответ разработчика не работает на iOS 7, но, немного изменив ситуацию, мне удалось получить доступ к тому, что мне было нужно. Вот код, который я использовал:

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

Из того, что я мог разобрать, в iOS 7 клавиатура состоит из UIPeripheralHostView, содержащего два подзаголовка: a UIKBInputBackdropView (который обеспечивает эффект размытия на любом под клавиатурой) и UIKeyboardAutomatic (который обеспечивает клавиши символов). Манипуляция UIPeripheralHostView кажется эквивалентной манипуляции всей клавиатурой.

Discaimer: я не знаю, примет ли Apple приложение, использующее эту технику, и не будет ли оно работать в будущих SDK.

Ответ 4

Имейте в виду, что Apple ясно сообщила, что приложения, которые изменяют иерархию частного представления без явного подтверждения заранее, будут отклонены. Взгляните на форумы Apple Developer для различных опытов разработчиков по этой проблеме.

Если вы просто пытаетесь отключить клавиатуру (чтобы она не получала штрихи), вы можете попробовать добавить прозрачный UIView, который является полным размером экрана для текущей ориентации. Если вы добавите его в качестве подзона в главном окне, это может сработать. Apple не сделала публичного метода отключения клавиатуры, о которой я знаю, - вы можете использовать один из ваших инцидентов с поддержкой Apple, возможно, они позволят вам решить проблему.

Ответ 5

Для приложения, которое я сейчас разрабатываю, я использую очень быстрый и простой способ:

Добавьте это в файл заголовка:

// Add in interface
UIWindow * _window;

// Add as property
@property (strong, nonatomic) IBOutlet UIView * _keyboard;

Затем добавьте этот код в нижней части функции keyboardWillShow:

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

Этот код ищет, когда клавиатура поднята, а затем выделяет текущее окно. Затем я добавил таймер, чтобы выделить клавиатуру, так как были некоторые проблемы при распределении сразу.

- (void)allocateKeyboard {

    if (!_keyboard) {
        if (_window.subviews.count) {

            // The keyboard is always the 0th subview
            _keyboard = _window.subviews[0];
        }        
    }
}

Теперь у нас есть выделенная клавиатура, которая дает вам прямой "доступ" к клавиатуре по мере запроса.

Надеюсь, что это поможет

Ответ 6

В iOS 8 вам кажется, что вам нужно прыгать по цепочке больше, чем в прошлом. Следующее работает для меня, чтобы получить клавиатуру, хотя с доступными пользовательскими клавиатурами, и я не стал бы полагаться на эту работу, если вы не работаете в контролируемой среде.

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