iOS

iOS UIResponder 的学习

Posted by Puqin Chen on 2018-03-28

UIView 的指责之一是处理事件,一个视图是一个事件响应者,可以处理点击等事件。而这些事件就是在 UIResponder 类中定义的。

一个 UIResponder 类为那些需要响应并处理事件的对象定义了一组接口。这些事件主要分为两类:触摸事件和运动事件。

在 UIKit 中,UIApplication、UIView、UIViewController 这几个类都是直接继承自 UIResponder 类。这些对象都有响应事件的能力,因此也被称为响应对象,或者响应者。

响应链

大多数事件的分发都是依赖响应链的。响应链是由一系列链接在一起的响应者组成的。一般,一条响应链开始于第一响应者,结束于 application 对象。如果一个响应者不能处理事件,则会将事件沿着响应链传到下一响应者。

构建响应链

在 APP 中,所有的视图都是按树状层次结构组织起来的。除了根视图,每个视图都有一个父视图,也可以有多个或0个子视图,由此就构成了一条条的事件响应链。

确定第一响应者

  1. 当用户触发某一事件后,UIKit 会创建一个事件对象(UIEvent),然后事件对象被放到一个事件队列中(队列按照FIFO处理事件)。
  2. 当处理事件时,程序的UIApplication 对象会从队列的头部取出一个事件对象,并将其分发出去。
  3. 通常首先是将事件分发给程序的主UIWindow对象,对于触摸事件来说,window 会尝试将事件分发给触摸事件发生的那个视图上(被称为hit-test视图),查找的过程就是 hit-testing。
  4. 系统使用 hit-testing 来找到触摸下的视图,它检测一个触摸事件是否发生在相应视图对象的边界内(即视图的frame)。如果在,则会递归检测其所在的子视图。包含触摸点的视图层次架构中最底层的视图就是 hit-test 视图。在检测出 hit-test 后,系统就会将事件发送给这个视图来进行处理。

hit-test视图可以最先去处理触摸事件,如果hit-test视图不能处理事件,则事件会沿着响应链往上传递,直到找到能处理它的视图。

事件传递

最先可以处理事件的对象就是 hit-test 视图或第一响应者。如果这两者都不能处理,UIKit 会将事件传递到响应链中的下一个响应者。每一个响应者确定其是否要处理事件或者是通过nextResponder方法将其传递给下一个响应者。这一过程一直持续到找到能处理事件的响应者对象或者最终没有找到响应者。

响应链