You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS为何仅显示inputAccessoryView未弹键盘时会触发keyboardWillShow通知

问题根因分析

1. 无键盘弹出时触发keyboardWillShow通知的原因

你重写了当前视图控制器的canBecomeFirstResponder返回true,视图控制器加载后会自动成为第一响应者。系统为了加载并展示控制器绑定的inputAccessoryView,会主动派发UIResponder.keyboardWillShowNotification通知,此时通知携带的keyboardFrameEndUserInfoKey对应的高度等于你的chatBoxView高度,并非真实系统键盘的高度,所以会出现你看到的“没弹键盘也触发通知”的现象。

2. 收起键盘后再次触发keyboardWillShow通知的原因

当你点击空白处收起键盘时,当前第一响应者是chatBoxView内部的growingTextView,调用endEditing后growingTextView会resign第一响应者。此时系统检测到当前页面的视图控制器canBecomeFirstResponder返回true,会自动将控制器重新置为第一响应者,再次触发加载inputAccessoryView的流程,因此会先走keyboardWillHide,之后立刻触发keyboardWillShow。

修复方案
  • 先在keyboardWillShow方法中增加高度过滤逻辑,排除仅加载inputAccessoryView的场景:
@objc func keyboardWillShow(notification: Notification) {
    guard let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height else { return }
    // 真实键盘弹出时高度必然大于inputAccessoryView高度,过滤无效通知
    guard keyboardHeight > chatBoxView.frame.height else { return }
    print("Notification: Keyboard will show")
    DispatchQueue.main.async {
        self.tableView.setBottomInset(to: keyboardHeight - self.chatBoxView.frame.height)
        self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .bottom, animated: true)
    }
}
  • 如果不需要常驻显示输入框,可以调整实现逻辑:将chatBoxView作为普通子视图钉在页面底部,仅在growingTextView成为第一响应者时,将其设置为growingTextView的inputAccessoryView,彻底避免控制器作为第一响应者带来的多余通知。
  • 如果需要保留现有常驻输入框的实现,可在growingTextView结束编辑时,主动调用控制器的resignFirstResponder(),避免控制器自动成为第一响应者触发重复通知。

内容的提问来源于stack exchange,提问作者infiniteObj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 20:36:04