UILongPressGestureRecognizer设minimumPressDuration为.zero时touchesBegan不触发原因
底层原因解析
这个现象本质是UIKit的手势识别优先级和事件分发逻辑的内部规则导致的,具体可以拆解为三点:
- 首先明确UIKit的触摸事件分发基础逻辑:所有触摸事件产生后,会先传递给对应视图上绑定的手势识别器处理,只有手势识别器判定当前触摸不匹配自己的识别规则时,才会将事件下发给UIResponder的
touchesBegan/touchesMoved/touchesEnded系列响应方法。 - 当
UILongPressGestureRecognizer的minimumPressDuration设置为.zero时,UIKit内部会对这个值做特殊判断:识别时长为0意味着触摸按下的瞬间就可以判定手势识别成功,这时候系统会直接取消后续向普通响应者的事件分发,所以你的自定义MyView和ViewController的touchesBegan都不会被触发。 - 当
minimumPressDuration设置为.leastNormalMagnitude时,虽然这个值本身极小(约为1e-38量级),但它本质上不等于0,UIKit不会触发上述特殊逻辑,会遵循标准的长按手势识别流程:- 触摸按下后,先将事件下发给响应链的
touchesBegan方法 - 等待指定的
minimumPressDuration时长后,判定手势识别成功 - 此时如果手势的
cancelsTouchesInView属性为默认的true,才会调用响应者的touchesCancelled方法取消后续的触摸事件回调
所以你可以正常收到touchesBegan的触发。
- 触摸按下后,先将事件下发给响应链的
补充:你也可以通过手动设置手势的
delaysTouchesBegan = false来强制系统在手势识别前就下发touchesBegan事件,不过你目前用.leastNormalMagnitude的方案已经是iOS开发中通用的兼容方案。
内容的提问来源于stack exchange,提问作者x670
相关产品推荐
相关产品推荐

