如何让UITableView中的UITextView可点击,解决单元格点击异常问题
问题原因
UITextView的交互优先级高于单元格,默认会拦截所有触摸事件,不会向下传递到UITableViewCell的响应链。你开启的selectable和userInteractionEnabled是用于让UITextView本身响应选中文本、点击链接、编辑等交互,反而会强化其事件拦截优先级,无法解决单元格点击被拦截的问题。
解决方案
场景1:仅用UITextView展示富文本,不需要任何交互
直接关闭UITextView的用户交互即可,所有触摸事件会自动透传到下层单元格:
// Swift textView.isUserInteractionEnabled = false
// Objective-C textView.userInteractionEnabled = NO;
场景2:需要保留UITextView的选中文本、点击链接等交互,同时支持点击空白区域触发单元格点击
有两种常用实现方式可选:
方案A:添加点击手势手动触发单元格选中
给UITextView添加点击手势,判断点击位置不是链接/选中区域时,手动调用单元格的选中代理方法:
- 配置手势
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTextViewTap(_:))) tap.cancelsTouchesInView = false tap.numberOfTapsRequired = 1 tap.delegate = self textView.addGestureRecognizer(tap)
- 实现手势响应逻辑
@objc private func handleTextViewTap(_ gesture: UITapGestureRecognizer) { let location = gesture.location(in: textView) // 点击到链接时不触发单元格点击 if let pos = textView.closestPosition(to: location), let linkAttr = textView.textStyling(at: pos, in: .forward)?[.link], linkAttr != nil { return } // 找到textView所在的单元格 var currentView: UIView? = textView while currentView != nil { if let cell = currentView as? UITableViewCell, let indexPath = tableView.indexPath(for: cell) { tableView.delegate?.tableView?(tableView, didSelectRowAt: indexPath) break } currentView = currentView?.superview } }
- 实现手势代理避免和内置手势冲突
extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } }
方案B:自定义UITextView透传非必要事件
重写UITextView的hitTest方法,不需要textView响应的事件直接透传给父视图:
class PassThroughTextView: UITextView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { // 点击到链接/处于编辑/选中状态时,由textView响应 if let pos = closestPosition(to: point), let linkAttr = textStyling(at: pos, in: .forward)?[.link], linkAttr != nil || isFirstResponder || isSelected { return super.hitTest(point, with: event) } // 其余事件透传 return nil } }
后续把你用到的UITextView的类指定为PassThroughTextView即可。
注意事项
如果需要支持UITextView编辑功能,要在逻辑中额外判断isFirstResponder状态,编辑状态下优先由textView响应所有事件,避免输入被打断。
内容的提问来源于stack exchange,提问作者tHatpart
相关产品推荐
相关产品推荐

