您的位置:首页 > 移动开发 > IOS开发

IOS中触摸事件(touch event)的分发以及响应者链(The Responder Chain)机制理解

2014-07-26 22:00 881 查看
最近在看官方的Programming Guide, 恰好看到了事件处理这一部分, 结合网上众多贡献者的理解, 我也来分享自己对于这部分的理解.

IOS的应用是基于事件驱动(Event-driven)的, 当我们编写IOS APP的时候, 我们需要做的就是编写代码来处理好IOS运行周期中发生的各个类型的事件.  在IOS APP的生命周期中, 会产生各种各样的事件, 比如电量不足, 突然的来电, 网络连接断开了, 用户手指触碰屏幕等, 都会产生事件.
有些事件是交由系统底层进行处理, 并不会暴露给我们, 而有些事件, 比如触击事件(touch event), 当触击事件在app运行期间发生时, 若处于合适的状态(比如我们的应用处于前台并且是在激活的状态下,激活状态下的应用表现为正在运行并且可以接收事件)这样的事件是可以交由我们的app进行处理的.

这里就来谈谈触击事件(touch event)

假定你的app处于激活状态, 当你点击了屏幕, 系统底层便会收到触击的消息, 然后生成事件(event), 放入事件队列(event queue)中, 对于触击事件, 当事件队列处理到此事件时, 将其交由你的app, 接着, 你的app将这个触击事件与其他相关的信息(与UIKit有关的一些属性)一起打包为一个UIEvent对象.然后UIApplication(你的应用程序单例)对象
将打包的UIEvent(也就是那个触击事件)交由你应用程序的主Window进行分发. 这个过程可以由如下如表示:



上图中, UIWindow在寻找具体的View的过程中, 主要是使用了两个方法,hitTest:withEvent: 与 pointInside:withEvent:这两个方法来寻找发生触击事件的UIView对象.

见下图:



通过这样类似二分搜索的调用这两个方法去寻找触击发生的视图, 下面给出一个例子, 见图:



图中紫色的view就是触击发生的View. 

这里需要注意的是, 

1.当一个View的子视图的bounds大于View的bounds的时候, 点击子视图在其父视图bounds之外的部分, 是不会响应其触击事件的, 因为当点击在父视图bounds之外的部分时, 父视图的pointInside:withEvent:返回的是NO. 这时候就不会对子视图进行hitTest:withEvent:的调用了. 

2.若一个View的(隐藏)hidden属性设置为YES, 或者是禁止用户进行交互(userInteractionEnabled)设置为YES, 以及视图的alpha(透明度)小于0.01.那么这个视图将被hitTest:withEvent:方法忽略.

3.通过重载View的hitTest:withEvent:方法可以实现某些特定的目的.

下面用介绍响应者链(responder chain)

UIKit里面存在一个类, 叫做UIResponder, 这个类能够响应以及处理事件. 而继承这个类的对象都可以作为响应者. UIView, UIApplication, UIViewController, UIWindow都是从这个类里继承的. 响应者构成响应者链, 具体可以看如下图:



对于触击事件, 若发生触击的UIView对象不能处理, 那么事件就进入响应者链中去寻找响应者. 一般来说, 发生触击的hitTest-view作为第一响应者(first responder)处在响应者链的最前面, 响应者对象都有一个nextResponder的方法来获取响应者链中的下一个响应者的引用

参考的文档:
https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html#//apple_ref/doc/uid/TP40009541-CH4-SW2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐