iOS聊天视图控制器UITextField键盘无法正常收起问题求助
排查ChatScreenVC中UITextField键盘无法正常收起的问题
让我帮你一步步梳理这个键盘收起的异常问题,你已经做了不少尝试,不过有几个关键细节可能被忽略了,咱们逐个排查:
1. 最可能的根源:UITextField代理未绑定
你已经实现了UITextFieldDelegate协议和textFieldShouldReturn方法,但在viewDidLoad里没有设置chatInput.delegate = self!这会导致:
- 点击键盘的返回键时,
textFieldShouldReturn根本不会被调用(你打印的"THIS IS HAPPENING!"应该也没在控制台输出吧?) - 代理方法失效后,键盘的默认返回收起逻辑也无法触发
修复方案:在viewDidLoad中添加一行代码:
override func viewDidLoad() { super.viewDidLoad() chatLog.text = chatLogString chatLog.isEditable = false chatInput.autocorrectionType = .no // 新增:绑定UITextField代理 chatInput.delegate = self }
2. 键盘通知的注册与移除不完整
你在viewDidDisappear里只移除了UIKeyboardWillShow的通知,但没有移除UIKeyboardWillHide的通知,这会导致通知残留,可能干扰键盘的正常状态。另外,建议把通知注册移到viewWillAppear,移除移到viewWillDisappear,更符合ViewController的生命周期逻辑,避免重复注册。
修复方案:
override func viewWillAppear(_ animated: Bool) { setupView() animateView() // 移到这里注册键盘通知 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } override func viewWillDisappear(_ animated: Bool) { chatInput.resignFirstResponder() // 移除所有相关通知 NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 只保留SMACK_TALK通知的注册 NotificationCenter.default.addObserver(self, selector: #selector(self.reloadData), name: Notification.Name(rawValue: SMACK_TALK), object: nil) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: SMACK_TALK), object: nil) }
3. 优化sendTapped方法的执行逻辑
你在发送按钮点击事件里已经调用了resignFirstResponder和view.endEditing(true),但可以做两个优化确保生效:
- 用
guard更严谨地判断输入内容(过滤空白字符) - 确保UI操作在主线程执行(虽然默认是主线程,但避免异步操作干扰)
修复后的sendTapped:
@IBAction func sendTapped(_ sender: Any) { // 过滤空白字符,避免空消息或纯空格消息 guard let message = chatInput.text?.trimmingCharacters(in: .whitespacesAndNewlines), !message.isEmpty else { return } gameDelegate?.sendChat(message: message) chatInput.text = "" // 确保在主线程执行键盘收起操作 DispatchQueue.main.async { self.chatInput.resignFirstResponder() self.view.endEditing(true) } }
4. 完善键盘弹出/收起的布局动画
你修改了viewCenterConstraint来适配键盘,但没有触发布局动画,这可能导致视图更新不及时,间接影响键盘的状态。添加动画和layoutIfNeeded()可以确保布局平滑更新:
修复键盘通知方法:
@objc func keyboardWillShow(_ notification: Notification) { if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue { let keyboardHeight = keyboardFrame.cgRectValue.height viewCenterConstraint.constant = -keyboardHeight // 触发布局动画 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } } @objc func keyboardWillHide(_ notification: Notification) { viewCenterConstraint.constant = 0 // 触发布局动画 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } }
5. 排查其他潜在干扰
如果以上修复后还是有问题,可以检查:
- 是否在
reloadData或SMACK_TALK通知的回调中,不小心调用了chatInput.becomeFirstResponder()? - 有没有其他手势或第三方库拦截了UITextField的响应链?
先从绑定代理这个最基础的步骤开始试,大概率能解决你的问题!
内容的提问来源于stack exchange,提问作者dvd.Void
相关产品推荐
相关产品推荐

