点击UITableView时禁用UITapGestureRecognizer以实现单元格交互问题
解决点击UITableView时禁用隐藏键盘的Tap手势问题
这个问题我做项目时也碰到过——给整个view加了点击隐藏键盘的手势后,tableView的cell点击完全没反应,原因就是手势把tableView的触摸事件给拦截了。下面给你两种可行的解决方案,选适合你代码结构的就行:
方案一:给手势添加代理,过滤TableView的触摸
这是最直接的方法,通过手势代理判断触摸的区域是不是在tableView范围内,如果是,就让手势不响应,把事件交给tableView处理。
具体步骤:
- 让你的ViewController遵循
UIGestureRecognizerDelegate协议; - 在添加手势时设置它的delegate;
- 实现代理方法,排除tableView及其子视图的触摸。
代码示例:
class YourViewController: UIViewController, UIGestureRecognizerDelegate { // 关联你的两个TableView @IBOutlet weak var firstTableView: UITableView! @IBOutlet weak var secondTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // 创建并添加隐藏键盘的Tap手势 let hideKeyboardTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) hideKeyboardTap.delegate = self view.addGestureRecognizer(hideKeyboardTap) // 别忘了配置你的TableView数据源和代理... } @objc private func dismissKeyboard() { view.endEditing(true) } // 核心:判断手势是否要接收当前触摸事件 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { guard let touchedView = touch.view else { return true } // 如果触摸的是任意一个TableView或者它的子视图(比如cell、cell里的控件),就不让手势响应 let isTouchingTableView = touchedView.isDescendant(of: firstTableView) || touchedView.isDescendant(of: secondTableView) return !isTouchingTableView } }
方案二:优化通用扩展(如果你用了全局隐藏键盘的扩展)
如果你是通过UIViewController的扩展来实现全局点击隐藏键盘,那可以修改扩展,让它支持传入需要排除的视图:
扩展代码:
extension UIViewController { func setupHideKeyboardOnTap(excluding excludedViews: [UIView] = []) { let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) tapGesture.delegate = TapGestureDelegate(excludedViews: excludedViews) view.addGestureRecognizer(tapGesture) } @objc private func dismissKeyboard() { view.endEditing(true) } } // 自定义手势代理类,专门处理排除视图逻辑 private class TapGestureDelegate: NSObject, UIGestureRecognizerDelegate { private let excludedViews: [UIView] init(excludedViews: [UIView]) { self.excludedViews = excludedViews super.init() } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { guard let touchedView = touch.view else { return true } // 检查触摸的视图是否属于要排除的视图层级 for excludedView in excludedViews { if touchedView.isDescendant(of: excludedView) { return false } } return true } }
在ViewController里使用:
override func viewDidLoad() { super.viewDidLoad() // 传入要排除的两个TableView setupHideKeyboardOnTap(excluding: [firstTableView, secondTableView]) }
这样一来,点击两个TableView的任何区域都不会触发隐藏键盘的手势,同时cell的点击、滑动等交互都能正常工作啦。
内容的提问来源于stack exchange,提问作者Miquel Molina
相关产品推荐
相关产品推荐

