1、事件处理
在用户使用app过程中,会产生各种各样的事件,iOS中的事件可以分为3大类型:触摸事件、加速计事件和远程控制事件,如下图所示:
这里我们主要说说触摸事件,发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列,UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步,找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理
touchesBegan…
touchesMoved…
touchedEnded…
要想找到最合适的视图来处理事件,首先我们得必须清楚事件是如何传递的,如下图所示:
触摸事件的传递是从父控件传递到子控件,我们来分析下以下几种视图被点击后事件的传递过程
点击了绿色的view:
UIApplication->UIWindow->白色 ->绿色
点击了蓝色的view:
UIApplication->UIWindow->白色 ->橙色 ->蓝色
点击了黄色的view:
UIApplication->UIWindow->白色 ->橙色 ->蓝色 ->黄色
值得注意的是: 如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸 事件。
那么问题来了,如何找到最合适的控件来处理事件?可以通过2点因素判断:
1、自己是否能接收触摸事件;
2、触摸点是否在自己身上。
之后就从后往前遍历子控件(
注:先遍历后添加的子控件),重复前面的两个步骤,如果没有符合条件的子控件,那么就自己最适合处理,这就是触摸事件的传递。
那么UIView在什么情况下不能接收触摸事件呢?一共有三种情况:
1.不接收用户交互
userInteractionEnabled = NO
2.隐藏
hidden = YES
3.透明
alpha = 0.0 ~ 0.01
提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的。
触摸事件处理的详细过程
用户点击屏幕后产生的一个触摸事件,经过一些列的传递过程后,会找到最合适的视图控件来处理这个事件。找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理
touchesBegan…
touchesMoved…
touchedEnded…
如果最合适的视图控件没有实现touchs方法,这些touches方法的默认做法是将事件顺着
响应者链条向上传递,将事件交给
上一个响应者进行处理。
2、响应者链条
下图是我从Apple官方文档截下来的关于响应者链条的示意图:
参照以上两幅图,我们基本可以理清
响应
者链的事件传递过
程:
1.如果当前处理事件的view是控制器的view,就传递给控制器(上一个响应者);其他情况下,则将其传递给它的父视图(上一个响应者)
2.在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
3.如果window对象也不处理,则其将事件或消息传递给UIApplication对象
4.如果UIApplication也不能处理该事件或消息,则将其丢弃
其实这里和事件处理里说的上一个响应者也就是官方文档截图里标注的nextResponder,如果当前处理触摸事件的view没有实现touchs方法,则会找寻它的nextResponder,如果没有则继续找,继而形成一个响应者链条,而且我们可以发现它的传递过程和事件处理的传递过程正好相反,形成一个回路似的路线