如何通过3D Touch获取点击视图引用?当前索引路径获取错误
关于3D Touch获取被点击视图引用的解决方案
当然可以通过3D Touch获取到被点击视图的引用,你遇到的indexPath不正确的问题,核心原因是传入的location参数是相对于当前视图控制器的view的坐标,而不是你的detailedTableView的局部坐标系,直接用它去查询tableView的行号自然会出错。
第一步:修正indexPath的获取逻辑
先把全局坐标转换成tableView的局部坐标,再去获取正确的indexPath和cell:
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { // 将全局location转换为tableView内部的坐标 let tableViewLocalPoint = detailedTableView.convert(location, from: self.view) guard let indexPath = detailedTableView.indexPathForRow(at: tableViewLocalPoint), let targetCell = detailedTableView.cellForRow(at: indexPath) else { return nil } // 后续操作... }
第二步:获取带tag的目标视图
如果你的cell内有带特定tag的子视图,或者你想直接定位到被点击的那个带tag的视图,可以用两种方式:
方式1:从cell中直接查找带tag的视图
如果目标视图是cell的直接子视图或后代视图,直接用viewWithTag(_:):
// 假设目标视图的tag是100 if let taggedView = targetCell.viewWithTag(100) { // 成功获取到带tag的视图引用,这里可以做你需要的逻辑处理 print("获取到目标视图:\(taggedView)") }
方式2:直接定位被点击的具体视图
如果想精准找到用户3D Touch点击的那个视图(可能是cell内的某个子视图),可以用hitTest(_:with:)方法:
// 找到被点击的最上层视图 if let hitView = detailedTableView.hitTest(tableViewLocalPoint, with: nil) { // 从该视图向上查找带tag的目标视图(如果目标视图是它的父视图之一) let targetTaggedView = hitView.superview?.viewWithTag(100) ?? hitView.viewWithTag(100) if let validView = targetTaggedView { // 处理逻辑 } }
额外注意事项
- 确保你的视图tag在cell范围内是唯一的,避免拿到错误的视图;
- 如果tableView有header或footer,
indexPathForRow(at:)会返回nil,guard语句会自动过滤这种情况; - 如果目标视图被其他视图遮挡,
hitTest会返回上层的遮挡视图,这时你可能需要调整视图层级,或者通过cell的indexPath间接定位目标视图。
内容的提问来源于stack exchange,提问作者Alok
相关产品推荐
相关产品推荐

