UITextField轻触无法唤起键盘仅长按有效问题排查与解决请求
问题分析与解决方案
你遇到的核心问题是手动给UISearchTextField添加的点击手势和它原生的触摸事件发生了冲突。UITextField本身自带了处理点击唤起键盘的逻辑,当你额外添加一个UITapGestureRecognizer到输入框上时,这个自定义手势会拦截掉原生的轻触事件,只有当长按或者多次点击(因为手势识别优先级的问题)时,原生事件才会触发,同时你的自定义手势逻辑(移除视图)也会干扰正常的键盘唤起流程。
另外,你的textFieldDidBeginEditing方法里还存在一个小错误:调用becomeFirstResponder()是多余的,此时textField已经处于开始编辑的状态,这个调用不仅没用,还可能导致额外的响应者混乱。
下面是具体的修复步骤:
1. 移除输入框上的自定义点击手势
删掉你给searchTextFieldData添加的hideTableView手势,我们不需要通过手势来实现点击输入框移除视图的逻辑,直接利用UITextFieldDelegate的方法即可。
2. 迁移视图移除逻辑到代理方法
把移除favouriteLabel和tableViewWithFavouriteBusStop的代码移到textFieldDidBeginEditing代理方法里,这样当用户轻触输入框开始编辑时,既会正常唤起键盘,也会执行移除视图的操作。
3. 修复代理方法的错误
删掉textFieldDidBeginEditing里多余的becomeFirstResponder()调用。
修改后的关键代码示例:
class DeparturesView: UIViewController { // ... 你的其他代码 ... private let searchTextFieldData: UISearchTextField = { let searchTextFieldData = UISearchTextField() searchTextFieldData.translatesAutoresizingMaskIntoConstraints = false searchTextFieldData.keyboardType = .alphabet searchTextFieldData.borderStyle = .roundedRect searchTextFieldData.autocorrectionType = .no searchTextFieldData.spellCheckingType = .no searchTextFieldData.layer.cornerRadius = 10 searchTextFieldData.backgroundColor = .white searchTextFieldData.returnKeyType = .search // 务必设置代理,否则代理方法不会触发 searchTextFieldData.delegate = self return searchTextFieldData }() override func viewDidLoad() { // ... 你的其他代码 ... //Mark - Add gesture to app func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return touch.view == self.view } //Mark - Hide keyboard let hideKeyboards = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))) hideKeyboards.delegate = self view.addGestureRecognizer(hideKeyboards) // --- 移除这段自定义手势代码 --- // let hideTableView = UITapGestureRecognizer(target: self, action: #selector(tapHandler)) // hideTableView.numberOfTapsRequired = 1 // hideTableView.delegate = self // searchTextFieldData.addGestureRecognizer(hideTableView) } // --- 可以删除这个tapHandler方法,逻辑已迁移到代理 --- // @objc func tapHandler(_ sender: UITapGestureRecognizer){ // print("Show tap tap") // favouriteLabel.removeFromSuperview() // tableViewWithFavouriteBusStop.removeFromSuperview() // } } extension DeparturesView: UITextFieldDelegate{ func textFieldDidBeginEditing(_ textField: UITextField) { // 在这里处理移除视图的逻辑 print("开始编辑,移除视图并唤起键盘") favouriteLabel.removeFromSuperview() tableViewWithFavouriteBusStop.removeFromSuperview() } // 可选:确保输入框可以正常进入编辑状态 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { return true } }
额外说明
- 原来的
hideKeyboards手势设置的shouldReceive逻辑是正确的,它只会响应点击self.view的事件,不会干扰输入框的触摸事件。 - 一定要给
searchTextFieldData设置代理(searchTextFieldData.delegate = self),否则代理方法不会被触发。
这样修改后,你轻触输入框就能正常唤起键盘,同时会自动移除指定的视图,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jakub Bąk




