本文为「iOS 事件响应者链」专题的总纲:定义响应者与响应者链、梳理历史与定位、说明事件处理的两阶段(hit-test 与响应链传递),并给出知识结构图与延伸阅读指引。分篇细节见 00-README 索引。
一、什么是响应者与响应者链
1.1 响应者(Responder)
在 UIKit 中,响应者指能够接收并处理系统事件(或转发给其他对象)的对象。所有响应者都是 UIResponder 的子类 [1]。
| 类型 | 说明 |
|---|---|
| UIApplication | 应用单例,响应者链顶端(或与 App Delegate 衔接) |
| UIWindow | 窗口,承载视图层级 |
| UIViewController | 视图控制器,其 view 为视图层级根节点时,常作为 view 的 next 响应者 |
| UIView | 视图(含 UIControl、UILabel 等),触摸事件的 hit-test 结果通常落在某 UIView 上 |
事件(触摸、按压、摇动、远程控制等)由系统投递给「最合适的响应者」——对触摸而言即 hit-test 得到的视图;对其他类型则可能是当前 First Responder。若该响应者不处理,事件会沿 响应者链(Responder Chain) 向下一节点传递,直到被处理或链结束 [2]。
1.2 响应者链(Responder Chain)
响应者链是由 nextResponder(在 API 中为 next)串联起来的一组响应者对象形成的链式结构。未处理的事件从「第一响应者」开始,依次传给 next,直到某节点处理或到达链尾(next == nil)[[1]][[2]]。
- 触摸事件:第一响应者 = hit-test 得到的视图(即「被点击」的最底层、最前端的子视图)。
- 按键/按压/摇动/编辑菜单等:第一响应者通常为当前获得焦点的对象(如 UITextField),或由系统/开发者指定。
链的构成规则由各子类的 next 实现决定,例如:UIView 的 next 为其所属的 UIViewController(若为 VC 的根 view)或 superview;UIViewController 的 next 为其 view 的 superview 或 window;UIWindow 的 next 为 UIApplication。详见 03-响应者链与 nextResponder 详解。
二、历史与定位
2.1 技术演进简述
响应者链源自 Cocoa/Cocoa Touch 的事件模型,与 Mac 上的 NSResponder 一脉相承:通过「响应者 + 链式传递」统一处理键盘、鼠标、触摸等输入,避免每个视图单独注册回调,便于解耦与复用 [3]。
| 阶段 | 要点 |
|---|---|
| Cocoa (Mac) | NSResponder、nextResponder、第一响应者与 key window,形成完整事件链 |
| UIKit (iPhone OS / iOS) | UIResponder 替代 NSResponder,触摸成为主要输入;hit-test 确定触摸的「第一响应者」 |
| 触屏优先 | 事件处理分为两阶段:先 hit-test(谁被点中),再 沿链传递(谁处理) |
| 手势与控件 | UIGestureRecognizer 优先于视图的 touches 方法;UIControl 的 target-action 可配合 nil target 走响应者链 |
2.2 在事件流中的定位
flowchart LR
subgraph 系统
A[硬件/系统事件]
end
subgraph 投递
B[UIApplication 接收]
C[hit-test 确定视图]
end
subgraph 处理
D[第一响应者]
E[沿 next 传递]
F[被处理或丢弃]
end
A --> B
B --> C
C --> D
D --> E
E --> F
- 阶段一(确定目标):触摸发生时,通过 hit-test(
hitTest(_:with:)/point(inside:with:))从 window 向下遍历视图树,得到「最底层且包含触点的视图」→ 作为该触摸事件的第一响应者。 - 阶段二(传递与处理):事件交给该视图;若其不处理(或未实现 touches 方法),则交给
nextResponder,依此类推,直至被处理或链结束。
2.3 泳道图:两阶段中系统与视图的协作
flowchart LR
subgraph 阶段一_HitTest
H1[Window]
H2[根 View]
H3[子 View 递归]
H4[命中 View]
H1 --> H2
H2 --> H3
H3 --> H4
end
subgraph 阶段二_响应链
R1[命中 View]
R2[next]
R3[VC / Window / App]
R4[处理或丢弃]
R1 --> R2
R2 --> R3
R3 --> R4
end
H4 --> R1
三、事件处理两阶段(总览)
| 阶段 | 方向 | 核心方法/机制 | 结果 |
|---|---|---|---|
| Hit-Testing | 自顶向下(Window → 子视图) | hitTest(_:with:)、point(inside:with:) | 得到「命中」的视图,即触摸的 first responder |
| Responder Chain | 自底向上(命中视图 → next → …) | next、touchesBegan 等转发 | 事件被某响应者处理或到达链尾 |
手势识别器(UIGestureRecognizer)在触摸到达视图的 touchesBegan 之前参与识别;若手势识别失败,触摸仍会交给视图并沿响应者链传递。详见 02-hitTest 与事件传递、03-响应者链与 nextResponder。
四、知识结构(思维导图)
mindmap
root((响应者链总纲))
响应者
UIResponder 子类
UIApplication / UIWindow / UIViewController / UIView
First Responder
Hit-Test
自顶向下
hitTest pointInside
子视图逆序
响应链
next 规则
触摸转发
target nil 与 Action
传递方式与编程模式
Delegate Block 闭包 函数封装
快速枚举 for 循环
事件类型
触摸 按压 摇动 远程
编辑菜单
五、延伸阅读
- 事件如何找到目标:02-hitTest 与事件传递详解
- 链如何构成、如何传递:03-响应者链与 nextResponder 详解
- 传递方式(Delegate/Block/闭包/函数封装/枚举与 for 循环):06-响应者链传递方式与编程模式详解
- UIResponder 与各类事件:04-UIResponder 与触摸及多类事件详解
- 工程应用与进阶:05-应用场景与进阶实践
参考文献
[1] UIResponder | Apple Developer Documentation
[2] Using responders and the responder chain to handle events
[3] Cocoa Application Competencies for iOS - Responder