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

点击UITableView时禁用UITapGestureRecognizer以实现单元格交互问题

解决点击UITableView时禁用隐藏键盘的Tap手势问题

这个问题我做项目时也碰到过——给整个view加了点击隐藏键盘的手势后,tableView的cell点击完全没反应,原因就是手势把tableView的触摸事件给拦截了。下面给你两种可行的解决方案,选适合你代码结构的就行:

方案一:给手势添加代理,过滤TableView的触摸

这是最直接的方法,通过手势代理判断触摸的区域是不是在tableView范围内,如果是,就让手势不响应,把事件交给tableView处理。

具体步骤:

  1. 让你的ViewController遵循UIGestureRecognizerDelegate协议;
  2. 在添加手势时设置它的delegate;
  3. 实现代理方法,排除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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:57:25