UIScrollView嵌套UITableView:轻触行时didSelectRowAt未触发(手势识别器拦截点击)
解决UIScrollView手势与UITableView行点击冲突的问题
这个问题我之前也碰到过!核心原因就是你给UIScrollView添加的UITapGestureRecognizer会优先拦截轻触事件,而UITableView的行点击本身依赖轻触手势,所以当你轻触表格行时,事件被ScrollView的手势抢了,表格的didSelectRowAt自然无法触发。拖动行时因为是拖动手势,和轻触手势不冲突,所以能正常响应。
下面给你两种实用的解决方案:
方案一:通过手势代理过滤表格区域的触摸
给你的轻触手势设置代理,在代理方法里判断触摸点是否落在UITableView范围内,如果是,就让手势不处理这个事件,把机会让给表格。
步骤1:给手势设置代理
// 假设你是这样创建手势的 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(endEditingOnTap)) tapGesture.delegate = self // 设置代理 yourScrollView.addGestureRecognizer(tapGesture)
步骤2:实现UIGestureRecognizerDelegate方法
extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { // 判断触摸的视图是否是tableView或它的子视图(比如cell) guard let touchView = touch.view else { return true } if touchView.isDescendant(of: yourTableView) { return false // 不接收表格区域的触摸,让表格自己处理 } return true // 其他区域的触摸由ScrollView手势处理 } }
方案二:给ScrollView空白区域单独加手势
如果你的需求只是轻触空白背景结束编辑,可以不给整个ScrollView加手势,而是给ScrollView的背景视图添加手势。这样只有点击空白区域才会触发结束编辑,表格和文本框的触摸事件完全不受影响。
// 创建一个覆盖ScrollView的背景视图,放在最底层 let bgView = UIView(frame: yourScrollView.bounds) bgView.backgroundColor = .clear // 透明不影响其他视图 yourScrollView.insertSubview(bgView, at: 0) // 给背景视图加轻触手势 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(endEditingOnTap)) bgView.addGestureRecognizer(tapGesture) // 别忘了在ScrollView bounds变化时更新bgView的frame(比如旋转屏幕) override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() bgView.frame = yourScrollView.bounds }
这两种方案都能解决你的问题,方案一更灵活,适合需要手势覆盖整个ScrollView但要排除特定区域的场景;方案二更简单,适合只需要空白区域触发手势的场景。
内容的提问来源于stack exchange,提问作者john
相关产品推荐
相关产品推荐

