UIKeyboardDidShow triggers too often?
Asked Answered
T

1

1

In order to display a text field right above the user's keyboard, I overrode inputAccessoryView in my custom view controller.
I also made sure that the view controller may become the first responder by overriding canBecomeFirstResponder (and returning true) and by calling self.becomeFirstResponder() in viewWillAppear().

Now, as I am displaying some messages as UICollectionViewCells in my view controller, I want to scroll down whenever the keyboard shows up. So I added a notification in viewDidLoad():

NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: Notification.Name.UIKeyboardDidShow, object: nil)

keyboardDidShow() then calls the scrolling function:

@objc private final func scrollToLastMessage() {
    // ('messages' holds all messages, one cell represents a message.)
    guard messages.count > 0 else { return }
    let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
    self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
}

Indeed, by setting breakpoints in Xcode, I found out that the function gets triggered after the keyboard has appeared. But additionally, it also triggers after I resigned the first responder (f.ex. by hitting the return key [I resign the first responder and return true in textFieldShouldReturn ]) and the keyboard has disappeared. Although I think that it shouldn't: as the Apple docs say:

Posted immediately after the display of the keyboard.

The notification also triggers when accessing the view controller, so after the main view has appeared and when clicking on a (customized) UICollectionViewCell (the cell does not have any editable content, only static labels or image views, so the keyboard shouldn't even appear).

To give some more information: I pretty much followed this tutorial on Youtube: https://www.youtube.com/watch?v=ky7YRh01by8

Teryl answered 17/6, 2018 at 17:55 Comment(4)
I would try logging the keyboard end frame in that function to see what its sizing information is. That should tell you when it is truly visible on screen.Syllogize
@Joey Thanks, that would definitely be a solution. Anyways, do you think that UIKeyboardDidShow should trigger when the keyboard didn't show, but only the inputAccessoryView appeared?Teryl
I do know that is intentional, as many apps don’t listen for keyboard frame changed, so to make it compatible with all apps it sends that did show notification with the new frame.Syllogize
@Joey Thanks, I now ended up with checking the userInfo dictionary that comes along with the notification. If it's greater than the height of my inputAccessoryView, I scroll down. If you like, you can provide an answer and I'd mark it as accepted.Teryl
S
2

The UIKeyboardDidShow notification may be posted more often than you might expect, not just when it initially appears. For example, when the frame changes after it was already visible, UIKeyboardDidShow is posted.

However you can know if the keyboard is truly visible by inspecting the keyboard's end frame from within the userInfo dictionary. This will tell you its size and position on screen, which you can then use to determine how best to react in your user interface.

Syllogize answered 18/6, 2018 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.