事件传递
说到事件传递,那么必不可少的会说到相关的2个方法
1.- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event;
2.- (BOOL)pointInside:(CGPoint)point withEvent(UIEvent*)event;
第一个方法返回的是一个UIView,是用来寻找到最终是那个视图来响应这个事件
第二个方法是用来判断点击的点是否在视图范围内,如果在就返回YES(true),反之则返回NO(false)
事件传递的流程描述
*我们点击屏幕产生触摸事件,系统将这个事件加入到一个由UIApplication管理的事件队列中,UIApplication会从消息队列里取事件分发下去,首先传给UIWindow
*在UIWindow中就会调用hitTest: withEvent:方法去返回一个最终响应的视图
*在hitTest:withEvent:方法中就回去调用pointInside: withEvent:去判断当前点击的point是否在UIWindow范围内,如果是的话,就会去遍历它的子视图来查找最终响应的子视图
*遍历的方式是使用倒序的方式来遍历子视图,也就是说最后添加的子视图会最先遍历,在每一个视图中都回去调用它的hitTest:withEvent:方法,可以理解为是一个递归调用
*最终会返回一个响应视图,如果返回视图有值,那么这个视图就作为最终响应视图,结束整个事件传递;如果没有值,那么就会将UIWindow作为响应者
总结:UIApplicaton -> Window -> UIViewControleler -> UIView -> subView
hitTest: withEvent: 的流程描述
*首先会判断当前视图的hiden属性、是否可以交互以及透明度是否大于0.01,如果满足条件则进入下一步,否则返回nil
*调用pointInside: withEvent:方法来判断这个点是否在当前视图范围内,如果满足条件则进入下一步,否则返回nil
*然后以倒序的方式遍历它的子视图,在每个子视图中去调用hitTest:withEvent:方法,如果有一个子视图返回了一个最终的响应视图,那么就将这个视图返回给调用方;如果全部遍历完成都没有找到一个最终的响应视图,并且点击位置在当前视图范围内,就将当前视图作为最终响应视图返回
图来自于(https://blog.csdn.net/BlackWolfSky/article/details/84594466)视图响应
首页我们要知道,事件传递和响应过程是相反的。
*响应者对象:是可以响应事件并对其进行处理的对象。UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口。UIApplication、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。 第一响应者是应用程序中当前负责接收触摸事件的响应者对象(通常是一个UIView对象)。
*响应者链条
在ios程序中每个控件的摆放是有前后关系的,这种先后关系构成的一个链条就叫响应者链。(由一系列“下一个响应者”组成)
*响应者链的事件传递过程
*如果当前view是控制器的view,那么控制器就是上一个响应者,事件就传递给控制器;如果当前view不是控制器的view,那么父视图就是当前view的上一个响应者,事件就传递给它的父视图
*在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
*如果window对象也不处理,则其将事件或消息传递给UIApplication对象
*如果UIApplication也不能处理该事件或消息,则将其丢弃
总结: subView -> UIView-> UIViewControleler -> Window -> UIApplicaton
网友评论