KeyboardDidShow 触发太频繁?

Posted

技术标签:

【中文标题】KeyboardDidShow 触发太频繁?【英文标题】:UIKeyboardDidShow triggers too often? 【发布时间】:2018-06-17 17:55:59 【问题描述】:

为了在用户键盘的正上方显示一个文本字段,我在我的自定义视图控制器中覆盖了inputAccessoryView。 我还确保视图控制器可以通过覆盖canBecomeFirstResponder(并返回true)和在viewWillAppear() 中调用self.becomeFirstResponder() 来成为第一响应者。

现在,当我在视图控制器中将一些消息显示为UICollectionViewCells 时,我想在键盘出现时向下滚动。于是我在viewDidLoad()添加了一条通知:

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

keyboardDidShow()然后调用滚动函数:

@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)

确实,通过在 Xcode 中设置断点,我发现该函数是在键盘出现后触发的。但此外,它也会在我辞去第一响应者之后触发(例如,通过按回车键 [我辞去第一响应者并在 textFieldShouldReturn 中返回 true ])并且键盘消失了。虽然我认为它不应该:正如苹果文档所说:

在键盘显示后立即发布。

在访问视图控制器时也会触发通知,因此在主视图出现后并单击(自定义)UICollectionViewCell(单元格没有任何可编辑内容,只有静态标签或图像视图,因此键盘甚至不应该出现)。

提供更多信息:我非常关注 Youtube 上的这个教程:https://www.youtube.com/watch?v=ky7YRh01by8

【问题讨论】:

我会尝试在该函数中记录键盘结束帧以查看其大小信息。这应该会告诉您它何时真正在屏幕上可见。 @Joey 谢谢,这绝对是一个解决方案。无论如何,您认为UIKeyboardDidShow应该在键盘没有显示而只有inputAccessoryView出现时触发吗? 我知道这是故意的,因为许多应用程序不会监听键盘框架的变化,因此为了使其与它发送的所有应用程序兼容,这些应用程序确实显示新框架的通知。 @Joey 谢谢,我现在检查了通知附带的 userInfo 字典。如果它大于我的inputAccessoryView 的高度,我向下滚动。如果您愿意,可以提供答案,我会将其标记为已接受。 【参考方案1】:

UIKeyboardDidShow 通知的发布频率可能超出您的预期,而不仅仅是在最初出现时。例如,当框架在可见后发生变化时,会发布UIKeyboardDidShow

但是,您可以通过从userInfo 字典中检查键盘的结束框来了解键盘是否真正可见。这将告诉您它在屏幕上的大小和位置,然后您可以使用它们来确定如何在您的用户界面中做出最佳反应。

【讨论】:

以上是关于KeyboardDidShow 触发太频繁?的主要内容,如果未能解决你的问题,请参考以下文章

UIButton touchDragEnter 和 touchDragExit 调用太频繁

在 KeyboardDidShow 上切换 UIBarButtonItem

js函数节流(解决频繁触发函数的性能问题)

键盘自动滚动?

函数防抖和节流*(性能优化不错的选择)

最频繁触发Android接收器?