Day1-UIKit事件传递机制 & Responder Chain

YVTU

UIKit 事件传递机制 & Responder Chain

一、事件类型

UIKit 中主要的事件类型包括:

  • 触摸事件(Touch Events):如 tap、swipe、pinch 等。
  • 运动事件(Motion Events):如摇动设备。
  • 远程控制事件(Remote-Control Events):如耳机控制、CarPlay。
  • 按键事件(Press Events)(仅限 tvOS 或支持硬件键盘时的 iOS)。

二、事件传递流程

  1. 事件产生

    • 事件由硬件(屏幕、传感器等)检测后交给系统。
    • iOS 将事件加入到主线程的 UIApplication 对象中进行分发。
  2. 事件分发路径

    • UIApplicationUIWindowUIView
  3. 命中测试(Hit-Testing)

    • 从根视图(window 的 rootView)开始递归查找目标视图。
    • 使用两个方法:
      • point(inside:with:)
      • hitTest(_:with:)
    • 最终找到最合适的视图接收触摸事件。

三、Responder Chain(响应者链)

1. 什么是 Responder Chain?

Responder Chain 是一条事件响应链,用来处理视图无法响应的事件。

2. Responder Chain 构成

一个 UIResponder 对象(如 UIView、UIViewController)可以传递事件给其上层响应者:
UIView → UIViewController → UIWindow → UIApplication → AppDelegate

如果某个对象无法处理事件,它会把事件传递给下一个响应者。

3. UIResponder 方法

方法名 说明
touchesBegan(_:with:) 开始触摸
touchesMoved(_:with:) 触摸移动
touchesEnded(_:with:) 触摸结束
touchesCancelled(_:with:) 触摸被取消

还可以通过 canBecomeFirstResponderbecomeFirstResponder() 控制焦点。


四、自定义事件传递(常见场景)

1. UIView 不响应事件

可能是因为以下原因:

  • isUserInteractionEnabled = false
  • alpha < 0.01
  • hidden = true

2. 自定义控件事件传递

可重写以下方法:

  • hitTest(_:with:):决定谁是事件的最终响应者。
  • point(inside:with:):判断点是否在当前视图内。

五、Responder Chain 应用场景

  • 控件事件传递:如 UIButton 点击事件向上传递。
  • 菜单处理:如复制粘贴菜单响应。
  • 键盘响应管理。
  • 自定义事件路由(target-action 无法处理时)。

六、调试技巧

  • 使用 View Debugger 检查视图层级。
  • 打断点调试 hitTesttouchesBegan
  • 查看 next 属性追踪 Responder Chain。

七、总结

  • UIKit 事件从 UIApplication 开始,经过 UIWindow 最终传递给具体的 UIView。
  • Responder Chain 是事件冒泡机制的实现,支持事件的多级处理。
  • 通过合理利用 hitTest:Responder Chain,可以实现复杂交互需求。