链接://www.greatytc.com/p/cb0314b72883
回到我们上面问过的问题,BView只有touchBegan, touchesCancelle 的原因是什么?答案在于整个触摸事件全过程
1.系统会通过hitTest的方法寻找响应链,完成之后会形成下图模型。
event handing squence.png
图中最右边是响应链,中间是关联在相应链在视图上的手势
2.有了模型之后就会发生图上的三个步骤
第一步:系统会将所有的 Touch message 优先发送给 关联在响应链上的全部手势。手势根据Touch序列消息和手势基本规则更改自己的状态(有的可能失败,有的可能识别等等)。如果没有一个手势对Touch message 进行拦截(拦截:系统不会将Touch message 发送给响应链顶部响应者),系统会进入第二步
第二步:系统将Touch message 发送给响应链 顶部的 视图控件,顶部视图控件这个时候就会调用Touch相关的四个方法中的某一个。之后进入自定义Touch message转发
第三步:自定义Touch message转发可以继承UIResponser的四个Touch函数做转发。
解释一下第一步中说的拦截,手势会表明是否拦截该Touch Message,主要由下面三个属性控制。
再回到那道题目,如果我们想hitTestView的toucheEnd函数依然能得到调用,怎么办?其实UIGestureRecognizer有三个属性
@property(nonatomic) BOOL cancelsTouchesInView; //defaultisYES. causes touchesCancelled:withEvent:orpressesCancelled:withEvent:tobe senttothe viewforalltouchesorpresses recognized as partofthis gesture immediately before the action methodiscalled.@property(nonatomic) BOOL delaysTouchesBegan; //defaultisNO. causesalltouchorpress eventstobe deliveredtothe target view onlyafterthis gesture has failed recognition. settoYEStoprevent views from processing any touchesorpresses that may be recognized as partofthis gesture@property(nonatomic) BOOL delaysTouchesEnded; //defaultisYES. causes touchesEndedorpressesEnded eventstobe deliveredtothe target view onlyafterthis gesture has failed recognition. this ensures that a touchorpress thatispartofthe gesture can be cancelledifthe gestureisrecognized
cancelsTouchesInView
默认为YES,表明当手势识别了该事件,系统会将Touch cancel消息发送给hitTestView ,并调用hitTestView的TouchCancel。设置为NO,不会再收到TouchCancel
delaysTouchesBegan
默认为YES, 表明无论什么情况下,不会拦截Touch began消息。如果设置为NO,只要有一个手势不识别失败,都不会发送Touch began到响应链的第一响应者。
delaysTouchesEnded
默认为NO, 和delaysTouchesBegan类似,不过它是用来控制TouchEnd message的拦截
总结
iOS整个事件处理的过程就是这样,系统为完成整个交互做了很多东西,核心点如下:
事件分发过程分为:1.寻找响应链;2.事件消息分发
响应网是事件响应的基础,响应链是事件响应的具体路径。
事件消息分发优先发送给手势集合,手势内部会做冲突处理,过滤消息。不被过滤的消息会传递给响应链对象。