译自官方文档:Using Responders and the Responder Chain to Handle Eventsapp
App 使用响应者对象接收和处理事件。一个响应者对象能够是UIResponder
类的任何实例,常见的子类包括UIView
,UIViewController
和UIApplication
。响应者接收原始事件数据,而且必定会处理事件或将其发送给另外一个响应者对象。当 app 接收到事件时,UIKit
会自动将该事件定向到最合适的响应者对象,即第一响应者(the first responder)。框架
未处理的事件会在一个活动的响应者链中,从一个响应者传递到另外一个响应者,这是响应者对象的动态配置(?)。 下图显示了一个 app 中的响应者,该程序的界面包含一个UILabel
,一个UITextField
,一个UIButton
和两个背景UIView
。 该图还显示了事件如何沿着响应者链从一个响应者转移到下一个响应者。测试
若是UITextField
不处理事件,则UIKit
会将事件发送到UITextField
的父视图,而后再接下来会发送到UIWindow
的根视图。从根视图开始,响应程序链在将事件定向到UIWindow
以前转移到当前持有的UIViewController
。若是UIWindow
没法处理事件,则UIKit
会将事件传递给UIApplication
对象,若是该对象是UIResponder
的实例而且还不是响应者链的一部分,则可能传递给app delegate(?)。ui
UIKit
是根据事件的类型将对象指定为该事件的第一响应者。事件类型包括:code
事件类型 | 第一响应者 |
---|---|
Touch events | 发生触摸的视图 |
Press events | 被 focus 的对象 |
Shake-motion events | 你(或UIKit )指定的对象 |
Remote-control events | 你(或UIKit )指定的对象 |
Editing menu messages | 你(或UIKit )指定的对象 |
注意cdn
与加速度计,陀螺仪和磁力计有关的运动事件不遵循响应程序链。 相反,Core Motion 会将这些事件直接传递到指定的对象。 有关更多信息,请参见 Core Motion 框架。对象
控件使用action信息直接与其关联的目标对象进行通讯。当用户与控件交互时,控件会将action信息发送到其target对象。action消息不是事件,可是它们仍然能够利用响应者链。当控件的目标对象为nil
时,UIKit
从目标对象开始并遍历响应程序链,直到找到实现适当操做方法的对象为止。例如,UIKit
编辑菜单使用此行为来搜索响应者对象,这些对象实现了诸如cut(_ :)
,copy(_ :)
或paste(_ :)
之类的方法。blog
手势识别器(Gesture recognizers)会比相关视图先接收触摸和按下事件。若是视图的手势识别器没法识别一系列触摸,则UIKit
会将触摸发送到视图。 若是视图没法处理触摸,UIKit
会将它们向上传递到响应者链。 有关使用手势识别器处理事件的更多信息,请参见处理UIKit
手势。事件
UIKit使用基于视图的命中测试(hit-testing)来肯定触摸事件发生的位置。具体来讲,UIKit将触摸位置与视图层次结构中视图对象的边界(bounds of view objects)进行比较。UIView
的hitTest(_:with :)
方法会遍历视图层次结构,查找包含指定触摸的最深子视图,该子视图成为触摸事件的第一响应者。ip
注意
若是触摸位置在视图范围(a view’s bounds)以外,则
hitTest(_:with :)
方法将忽略该视图及其全部子视图。所以,若是视图的clipsToBounds
属性为false
,即便该视图刚好包含触摸,也不会返回该视图范围以外的子视图。有关命中测试(hit-testing)行为的更多信息,请参见UIView
中有关hitTest(_:with :)
方法的讨论。
发生触摸时,UIKit
将建立一个UITouch
对象并将其与视图关联。 随着触摸位置或其余参数的更改,UIKit
会使用新信息更新那个UITouch
对象。 惟一不变的属性是那个关联的视图。 (即便触摸位置移到原始视图以外,触摸的视图属性中的值也不会更改。)触摸结束时,UIKit
会释放UITouch
对象。
您能够经过覆盖响应者对象的next
(指响应链中下一个响应者)属性来更改响应者链。
许多UIKit
类已经重写此属性并返回特定的对象,包括:
UIView
,若是视图是UIViewController
的根视图,则下一个响应者是UIViewController
。不然,下一个响应者是视图的父视图。
UIViewController
若是UIViewController
的视图是UIWindow
的根视图,则下一个响应者是UIWindow
对象。
若是UIViewController
是由另外一个UIViewController
呈现的,则下一个响应者是第二个视图控制器。
UIWindow
,窗口的下一个响应者是UIApplication
对象。
UIApplication
,下一个响应者是app delegate
.但仅当该app delegate
是UIResponder
的实例且不是视图、UIViewController
或app对象自己时,才是下一个响应者。
这篇文档讲得很浅,同时也讲的不怎么容易懂,想要更深刻理解响应链及手势相关内容仍是须要阅读更多其余优秀资料。