UIKeyboardDidShowNotification вызывается несколько раз, а иногда и с неправильными размерами клавиатуры
Я пытаюсь переместить UITextView над клавиатурой всякий раз, когда клавиатура появляется / изменяется. Предположим, у меня есть английская клавиатура, а затем переключитесь прямо на китайскую клавиатуру (которая выше стандартной английской клавиатуры). В этом сценарии мое текстовое представление всегда кажется слишком высоким (невооруженным глазом, похоже, что текстовое представление неправильно смещено размером китайской клавиатуры «вид вспомогательного аксессуара». Я бы разместил изображение, но мне не хватало репутации так 🙂 ). Я корректирую позицию в текстовом виде, когда мое приложение получает UIKeyboardDidShowNotification (используя UIKeyboardFrameEndUserInfoKey для получения высоты), и после некоторого исследования UIKeyboardDidShowNotification вызывается несколько раз, часто с неправильными размерами клавиатуры (у меня NSLogged словарь userInfo). Я регистрируюсь для своих клавиатурных уведомлений в ViewWillAppear и отменил регистрацию в ViewWillDisappear. Я не могу определить, что может вызвать многократное уведомление этого уведомления; я понимаю, что это уведомление должно быть уволено только один раз, сразу после того, как клавиатура закончит показ. Дополнительное примечание: я сам NSLogged «сам» в методе, который отвечает на UIKeyboardDidShowNotification, и на самом деле он всегда является одним и тем же объектом View Controller.
Тем не менее, даже если это уведомление срабатывает несколько раз, я до сих пор не понимаю, почему высота клавиатуры будет отличаться для некоторых из этих уведомлений. Одно из уведомлений всегда имеет правильную высоту, но когда последнее уведомление не срабатывает, просмотр текста заканчивается в неправильном месте. Любое понимание того, как дальнейшая диагностика будет оценено очень высоко!
EDIT: Чем больше я тестирую, тем больше проблема с китайской клавиатурой. Всякий раз, когда я переключаю клавиатуру с английского на китайский, я получаю три UIKeyboardWillShowNotifications:
- Клавиатура не исчезает после просмотраDidDisappear на iOS 7
- Внешний вид SLComposeViewController Dark Keyboard
- Цвет клавиатуры IOS7 Return / Done / Search
- как отключить uikeyboard textview, если включен режим редактирования
- UITableView не сдвигается при переходе с textField на textField напрямую
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]; }
- Разрешить полный доступ к пользовательской клавиатуре в iOS
- Как отключить десятичный ключ на клавиатуре iOS
- Действие кнопки «Go» на клавиатуре ios
- Установите UIKeyboardAppearance во всем приложении
- Клавиатура UITextField: активировать кнопку, когда текст не вводится
- UIKeyboardTypeDecimalPad с отрицательными номерами
- Числовая компоновка не липкая в безопасном UITextField?
- UIKeyboardWillShowNotification & UIKeyboardDidShowNotification сообщает о неправильной высоте клавиатуры
Ответ 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 здесь, как сказал 曹.