Why is UIKeyboardWillShowNotification called every time another TextField is selected?

onmyway133 picture onmyway133 · Mar 21, 2014 · Viewed 18k times · Source

I have a project that contains a UIScrollView and many UITextField inside it.

For the first time I select a UITextField, UIKeyboardWillShowNotification is called, which is fine. But whenever I select new UITextField (THE KEYBOARD IS STILL THERE), UIKeyboardWillShowNotification is called again !!!, which is weird.

I also set a symbolic breakpoint for [UIResponder resignFirstResponder] and I see that it is hit before and after UIKeyboardWillShowNotification is called !!!

The other thing is that UIKeyboardWillHideNotification is only called when I hit the "Done" button on the keyboard

I'm sure to not call any resignFirstResponder, becomeFirstResponder, endEditing anywhere. (I mean not call wrongly)

What can cause this problem ?

Here is the stacktrace enter image description here

Answer

paulvs picture paulvs · Aug 28, 2016

To workaround the problem, I used the following code to cancel the UIKeyboardWillShowNotification callback if the keyboard's frame is not changing.

func keyboardWillShow(notification: NSNotification) {

    let beginFrame = notification.userInfo![UIKeyboardFrameBeginUserInfoKey]!.CGRectValue()
    let endFrame = notification.userInfo![UIKeyboardFrameEndUserInfoKey]!.CGRectValue()

    // Return early if the keyboard's frame isn't changing.
    guard CGRectEqualToRect(beginFrame, endFrame) == false else {
        return
    }

    ...
}

For Swift 3/4:

func keyboardWillShow(notification: Notification) {

    let userInfo = notification.userInfo!
    let beginFrameValue = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)!
    let beginFrame = beginFrameValue.cgRectValue
    let endFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)!
    let endFrame = endFrameValue.cgRectValue

    if beginFrame.equalTo(endFrame) {
        return
    }

    // Do something with 'will show' event
    ...
}