it-swarm.com.ru

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

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

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

Правка: Чем больше я тестирую, тем больше, кажется, проблема именно с китайской клавиатурой. Всякий раз, когда я переключаю клавиатуру с английского на китайский, я получаю три 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];
}
13
Benny B

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

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

5
iwasrobbed

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

4
Big D
- (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 здесь как 曹 сказал.

0
DianeZhou

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

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

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

Я думаю, что "настройка" означает ViewDidLoad. И в списке "Обработка кода уведомлений клавиатуры" нет 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
}
0
henry ren