iOS中事件的传递和响应者链条

在iOS 开发中,常见的事件有三种类型,分别是:

(1)触摸事件:平常手指在屏幕上滑动,产生的事件都是触摸事件

(2)加速计事件:微信的摇一摇就是典型的加速计事件

(3)远程控制事件:耳机控制歌曲上一首、下一首、暂停就是远程控制事件的应用。

在触摸事件中,通常情况下,点击哪个控件,哪个控件就会产生反应。比如说,点击确定按钮,确定按钮会响应该事件,点击取消按钮,取消按钮会响应该事件。那么,系统是如何决定哪一个视图(控件)来响应该事件呢?

当发生触摸事件后,系统会将该事件加入到一个由 UIApplication 管理的队列中,UIApplication 会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口。主窗口会在整个视图层次结构中找到一个最合适的视图来处理该触摸事件。找到合适的视图控件后,就会调用该控件响应的方法来处理触摸事件,常用的方法有:

touchesBegan...

touchesMoved...

touchesEnded...

touchesCancelled...

在app 开发中,一个控制器下通常不止一个控件,那么发生触摸事件后,哪一个控件是最合适处理该事件的呢?

在确定最合适控件的过程中,遵循以下原则:

(1)判断自己能否接收触摸事件,如果不能,直接返回;如果能,到第(2)步

(2)判断触摸点是否在自己身上,如果不在,直接返回;如果在,到第(3)步

(3)从后往前遍历子控件,重复前两步

(4)如果没有符合条件的子控件,那么自己就是最适合处理该触摸事件的控件。

举例如下:

其中,绿色view和橙色 view都是白色view的子控件(假设先加入了绿色view,后加入了橙色view),蓝色view和红色view都是橙色view的子控件,黄色view是蓝色view的子控件。

当点击绿色view时,事件先传递到白色view。白色view满足条件(1),到步骤2,触摸点在自己身上,到步骤3,对橙色view做步骤(1)和步骤(2),不满足步骤(2),回退,对绿色view做步骤(1)和步骤(2),均满足,到步骤(3),没有子控件,到步骤(4),自己就是最合适的控件(绿色view)。整个的流程如下:

白色view --->橙色view(橙色view不满足步骤2,因此遍历绿色view)

            ---->绿色view(满足步骤1和步骤2),没有子控件,所以绿色view是最适合处理该触摸事件的控件。

当点击黄色view时,流程如下:

白色view --->橙色view --->红色view(红色view覆盖了蓝色view,可知红色view是后加入的。红色view不满足条件2,因此到蓝色view)

                                --->蓝色view --->黄色view(黄色view没有子控件,所以黄色view是最适合处理该触摸事件的控件)。

也就是说,在寻找最合适的子视图时,是从父视图控件开始,一层一层向下寻找的。

在找到最合适的视图控件后,就会调用控件的 touchesBegan... 等方法。这些touches的默认做法是将事件顺着响应者链条向上传递,交给上一个响应者处理

假设点击了上图中的黄色控件,如果黄色控件不处理该触摸事件,会将该事件交给蓝色控件处理;如果蓝色控件不处理该控件,会将该控件交给橙色控件处理;如果橙色控件不处理该事件,会将该事件交给白色控件来处理;如果白色控件不处理该事件,白色控件会交给控制器来处理;如果控制器不处理该事件,控制器会交给主窗口处理该事件;如果主窗口不处理该事件,主窗口会交给UIApplication来处理该事件;如果UIApplication也不处理该事件,则该事件会被丢弃,不做处理。因此说,事件的处理过程是顺着响应者链条向上传递的。

示意图如下:

左侧是单控制器,右侧是多控制器。

响应者链的事件传递过程总结如下:

1.如果view的控制器存在,就传递给控制器处理;如果控制器不存在,则传递给它的父视图

2.在视图层次结构的最鼎城,如果也不能处理收到的事件,则将事件传递给window对象进行处理

3.如果window对象也不处理,则将事件传递给 UIApplication对象

4.如果UIApplication也不能处理该事件,则将该事件丢弃。

上传一个验证响应者链的代码(MJ所写)

https://files.cnblogs.com/files/acBool/06-%E5%93%8D%E5%BA%94%E8%80%85%E9%93%BE%E6%9D%A1.zip

posted @ 2015-12-21 21:08  acBool  阅读(1014)  评论(0编辑  收藏  举报