Swift中触摸事件与手势共存及UITextView动态高度调整性能问题咨询
解决方案
手势与原生触摸共存实现逻辑
- 无需移除原有
pan/pinch/rotate手势,仅需实现UIGestureRecognizerDelegate的gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:代理方法,返回true即可允许手势识别器与原生触摸事件、多个手势之间同时触发,不会出现事件被拦截的问题。 - 原有触摸事件卡顿、触发不灵敏的核心原因是自行处理全量触摸点时没有做阈值过滤、多余计算过多,且移除了系统优化过的手势识别逻辑,不需要完全改用原生触摸方法实现高度调整。
最优实现方案(无性能损耗,无事件冲突)
优先新增专属手势处理高度调整,无需触碰原生触摸方法:
- 在
UITextView底部添加一个高度20pt的拖拽响应区域(可以是透明UIView作为拖拽把手,不影响原有UI展示) - 给这个拖拽把手单独添加一个
UIPanGestureRecognizer,专门用于处理高度调整逻辑 - 设置新手势的
delegate为当前控制器,允许和原有手势共存 - 拖拽时仅更新
UITextView的高度约束constant,实时调用父视图的layoutIfNeeded刷新布局即可
示例代码参考:
// 全局存储原始高度 var originalTextViewHeight: CGFloat = 100 // 初始化高度调整专用手势 let heightDragPan = UIPanGestureRecognizer(target: self, action: #selector(handleHeightDrag(_:))) heightDragPan.delegate = self dragHandleView.addGestureRecognizer(heightDragPan) // 实现手势共存代理 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } // 高度调整逻辑 @objc func handleHeightDrag(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: view) // 可自定义最小/最大高度限制 let newHeight = max(80, min(300, originalTextViewHeight + translation.y)) textViewHeightConstraint.constant = newHeight view.layoutIfNeeded() if gesture.state == .ended { originalTextViewHeight = newHeight } }
如果你必须使用原生触摸方法实现的优化点
如果因为业务要求必须用touchesBegan/touchesMoved处理,按以下规则优化即可解决卡顿问题:
- 仅在触摸点落在你指定的高度调整区域时才处理触摸逻辑,其余触摸事件直接调用
super方法传递给原有手势识别器 touchesMoved中仅做高度差计算,不要执行多余的文本重绘、约束重新创建等操作,仅修改高度约束的数值- 增加移动阈值判断,触摸点移动超过2pt再更新高度,避免无效的高频刷新
内容的提问来源于stack exchange,提问作者aqeedat zameer
相关产品推荐
相关产品推荐

