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

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

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

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

В моем случае я регистрируюсь для своих клавиатурных уведомлений в 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 } 
 - (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 здесь, как сказал 曹.

  • iOS - как убрать клавиатуру?
  • Держите клавиатуру всегда сверху и видимой
  • По какой причине UITableViewController не прокручивает активное текстовое поле при появлении клавиатуры?
  • UISearchBar вводит 2 символа, прежде чем кнопка поиска активна на UIKeyboard
  • Программно изменить тип клавиатуры UITextField
  • Раскладка клавиатуры Emoji неправильно рисуется и отсутствует много эмоций
  • UIView на клавиатуре похож на iMessage App
  • Невозможно найти клавиатуру, которая поддерживает тип 4 для клавиатуры. Предупреждение, возможно ли молчание?
  • Получение размера экранной клавиатуры iPad после вращения
  • Как я могу изменить свой входной параметрAccessoryView при повороте устройства?
  • Пользовательская реализация UITextInput не показывает многостадийные предложения ввода
  • Interesting Posts

    Как освободить объекты в NSMutableArray с помощью ARC?

    Быстрое правильное использование геттеров и сеттеров

    Сокращение пространства между компонентами UIPickerView

    Xcode 8 – Некоторые виды и VC не отображаются на симуляторе

    NSFetchedResultsController ОЧЕНЬ медленный

    Как синхронизировать основные данные ядра с веб-сервером, а затем нажать на другие устройства?

    isa указатель в объективе-c

    Невозможно передать обслуживание с Mac на iOS, хотя передача обслуживания с iOS на Mac работает нормально

    Popovers нельзя представить из представления, которое не имеет оконной ошибки

    Проблема с отложенными обновлениями местоположения ios

    Проблема с лексикой или препроцессором

    Настройка UIDatePicker

    prepareForSegue вызывается до didSelectRowAtIndexPath только при добавлении третьего segue

    Интервал RACSignal не работает сразу

    iOS: Получите «предупреждение о принимаемой памяти» после использования изображения, созданного из PDF и используемого в качестве фона

    Давайте будем гением компьютера.