Подтвердить что ты не робот

UIKeyboardDidShowNotification вызывается несколько раз, а иногда и с неправильными размерами клавиатуры

Я пытаюсь переместить UITextView над клавиатурой всякий раз, когда появляется или изменяется клавиатура. Скажем, у меня есть английская клавиатура, а затем переключается прямо на китайскую клавиатуру (которая выше стандартной английской клавиатуры). В этом сценарии мое текстовое представление всегда кажется слишком высоким (невооруженным глазом, похоже, что текстовое представление неправильно смещено размером китайской клавиатуры "вид вспомогательного аксессуара". Я бы разместил изображение, но мне не хватало репутации так:)). Я корректирую позицию в текстовом виде, когда мое приложение получает UIKeyboardDidShowNotification (используя UIKeyboardFrameEndUserInfoKey для получения высоты), и после некоторого исследования UIKeyboardDidShowNotification вызывается несколько раз, часто с неправильными размерами клавиатуры (у меня NSLogged словарь userInfo). Я регистрируюсь для своих клавиатурных уведомлений в ViewWillAppear и отменил регистрацию в ViewWillDisappear. Я не могу определить, что может вызвать многократное уведомление этого уведомления; я понимаю, что это уведомление должно быть уволено только один раз, сразу после того, как клавиатура закончит показ. Дополнительное примечание: я сам NSLogged "сам" в методе, который отвечает на UIKeyboardDidShowNotification, и на самом деле он всегда является одним и тем же объектом View Controller.

Тем не менее, несмотря на то, что это уведомление срабатывает несколько раз, я все еще не понимаю, почему высота клавиатуры будет отличаться для некоторых из этих уведомлений. Одно из уведомлений всегда имеет правильную высоту, но когда последнее уведомление не срабатывает, просмотр текста заканчивается в неправильном месте. Любое понимание того, как следует устранять неполадки, будет высоко оценено!

EDIT: чем больше я тестирую, тем больше проблема с китайской клавиатурой. Всякий раз, когда я переключаю клавиатуру с английского на китайский, я получаю три UIKeyboardWillShowNotifications:

2014-12-24 22:49:29.385 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 252}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 460}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 352}, {320, 216}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
}
2014-12-24 22:49:29.408 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 460}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 352}, {320, 216}}";
}
2014-12-24 22:49:29.420 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 288}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 424}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 280}, {320, 288}}";
}

Первая имеет правильную высоту конца: 252. Однако следующие два неверны в 216 и 288. Это происходит надежно.

Вот несколько фрагментов, демонстрирующих, как я управляю подписками на уведомления:

-(void)viewWillAppear:(BOOL)animated {

       [super viewWillAppear:animated];


       [self registerForKeyboardNotifications];


}

-(void)viewWillDisappear:(BOOL)animated {
       [super viewWillDisappear:animated];

       [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:UIKeyboardWillHideNotification
                                                object:nil];
       [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:UIKeyboardDidShowNotification
                                                object:nil];

}

- (void)registerForKeyboardNotifications {



      [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardWillHideNotification object:nil];

      [[NSNotificationCenter defaultCenter] addObserver:self      
                                         selector:@selector(keyboardDidShow:)                                       
                                             name:UIKeyboardDidShowNotification object:nil];
}
4b9b3361

Ответ 1

Если вы используете ярлык Cmd + K на симуляторе, чтобы отображать/скрывать клавиатуру, он может вызываться несколько раз, так как это не отменяет текстовое поле в качестве первого ответчика.

Если вы вместо этого используете клавиатуру Return, тогда она поступит правильно и уйдет в отставку.

Ответ 2

Ответ SWIFT: Основная причина заключается в том, что ваше уведомление вызывается несколько раз. Например, в swift, если у вас был NSNotificationCenter.defaultCenter(). AddObserver (xx "keyboardWillShow" xx) внутри метода viewWillAppear, и если вы идете туда и обратно между представлениями, это приведет к тому, что несколько наблюдателей будут иметь один и тот же "keyboardWillShow". Вместо этого вам следует переместить вызов addObserver в метод viewDidLoad(). В качестве альтернативы вы можете регистрировать/отменять регистрацию наблюдателя, когда представление появляется/исчезает.

Ответ 3

- (void)keyboardDidAppear:(NSNotification *)note {
    CGSize keyboardSize = [note.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
    textView.contentInset = contentInsets;
    textView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardWillBeHidden:(NSNotification *)note {
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    textView.contentInset = contentInsets;
    textView.scrollIndicatorInsets = contentInsets;
}

Решение от официального решения Apple здесь, как говорится.

Ответ 4

В моем случае я зарегистрирую свои уведомления о клавиатуре в ViewWillAppear и отменил регистрацию в ViewWillDisappear. Но, это приведет к тому, что обработчик UIKeyboardDidShowNotification будет запущен несколько раз. Похоже, что метод незарегистрированности не работает, поэтому каждый раз, когда появляется представление, подсчет Observer для UIKeyboardDidShowNotification plus 1. Затем вы касаетесь внутри UITextField, уведомляете несколько Observer, обработчик запускается снова и снова.

Итак, вы должны зарегистрироваться для уведомлений о клавиатуре в ViewDidLoad и не отменить регистрацию. Так же, как Apple, упомянутая на этой странице

//Вызовите этот метод где-нибудь в вашем коде настройки контроллера.

Я думаю, что "setup" означает ViewDidLoad.And В разделе "Обработка списка уведомлений клавиатуры" нет ViewWillDisappear.

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

   func keyboardWillShow(notification: NSNotification) {
    let userInfo = notification.userInfo!
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
    debugPrint("Before",NotifyView.frame)
    NotifyView.frame.offsetInPlace(dx: 0, dy: -keyboardHeight)
    debugPrint("After",NotifyView.frame)
}
func keyboardWillHide(notification: NSNotification) {//Do Nothing
}