赞
踩
NSLog(@"SHOW TIME...");
App通过响应者对象来接收和处理事件,响应者对象都是UIResponder的子类对象,常见的UIView,UIVieController、UIWindow和UIApplication都是UIResponder的子类。
- 当点击屏幕后,事件会传递给UIApplication,在由UIApplication传递给当前的UIWindow;
- UIWindow通过调用- (UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event方法返回响应视图。
- 其中hitTest:withEvent:内部会调用- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event方法判断点击位置是否在UIWindow范围内,
- 如果是的话就会【倒序遍历】(最后添加的视图最先遍历)UIWindow的子视图,从而找出响应视图并返回。
流程如下图1-1
图1-1 事件传递流程
1、 首先会判断当前视图是否有响应事件的能力,当视图隐藏属性hidden=NO、交互userInteractionEnabled=YES、透明度alpha>0.01三者同时满足才拥有响应能力。
2、 若当前视图未拥有响应能力,hitTest方法直接返回nil,并且将当前视图的父视图作为时间响应者返回。
3、 若当前视图拥有响应事件能力,则继续判断事件点击位置是否在当前视图范围内,若不在则输出效果同步骤2,若在范围内,则倒序遍历当前视图的子视图,重复以上动作,直到找出响应视图。
具体流程如图1-2
图1-2 hitTest:withEvent:内部实现流程
当事件触发后,系统会自动为我们找到合适的响应对象,响应对象对事件逐级向上响应的过程就是响应链,和事件传递流程可以说是恰好相反,如下图1-3
图1-3 事件响应链流程
图1-4 事件响应流程示例图
如图1-4,View A视图有View B2视图,View B2视图内有View C1和View C2两个子视图,此时点击空白圆的位置,系统会找到响应者C2视图,若C2视图不处理这个响应事件,会把事件传递给下一个响应者B2,若B2也不处理,在把事件传递给下一个响应者A视图,如果依旧不处理,则会沿着响应链向上传递直到传递给UIApplicationDelegate。如果一直没有视图响应事件的话,系统就会忽略这个事件(不会产生crash)。
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- 其中touches是一个存放UITouch对象的集合,UITouch对象保存着手指触摸相关信息,如触摸位置、时间等。
- 一根手指触摸,会调用一次touchesBegan:方法,并且touches集合中包含1个UITouch对象;
- 两根手指同时触摸一个view,view只调用一次touchesBegan:方法,并且touches集合中包含2个UITouch对象;
- 两根手指一前一后触摸一个view,view调用两次touchesBegan:方法,并且每次touches都只包含1个UITouch对象;
NSLog(@"END...");
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。