iOS事件传递和事件响应机制
这里主要讲解记录下用户触摸点击手机屏幕后产生的事件是如何派发传递的,如何查找到适合响应事件的第一响应者控件,以及找到响应者后事件是如何通过响应链向下传递的,直到事件被接收并做出具体处理或被废弃。事件响应链也是面试中经常会被问起的知识点!
第一响应者一般指的是用户当前触摸的响应者对象,表示当前该对象正在与用户交互,第一响应者是响应者链的开端。
具有响应和处理iOS事件能力的对象,也就是继承UIResponder的类的对象。我们常用的UIApplication、UIWindow、UIViewController、UIView、UIScene(iOS13以后)都是继承或间接UIResponder类,所以他们的实例对象都可以成为响应者对象。
类的继承关系:
由多个不同响应者对象链接起来构成的一个链条;
iOS中事件主要分为三大类:
1、Touch Event (触摸事件)
2、Motion Event (运动事件)
3、Remote-ControlEvent(远程控制事件)
测试展示图
当用户触摸屏幕时,系统会检测到屏幕上的压力感知到触摸事件,iOS系统检测到触摸操作后会将这个事件打包成一个UIEvent对象,并将该事件加入到一个由UIApplication管理的事件队列中,然后UIApplication会从事件队列中取出触摸事件并传递给UIWindow处理,keyWindow会使用hitTest:withEvent:方法寻找一个最合适的响应者来处理事件,一般寻找到的适合处理事件的控件是touch操作初始点的视图,找到合适第一响应者的视图控件后,就会调用该视图控件的touches方法来处理具体的事件,这个过程称之为hit-test。
事件的传递是由父控件向子控件传递的,例如上面的view层次图,viewA、viewB、viewE被添加到rootView中,viewC、viewD是viewB的子view。加入用户点击viewC的时间传递链是
传递方向:由底层系统向可以响应事件的控件传递
UIKit→UIApplication的事件队列→keyWindow→rootView→一些列subView→事件响应view
主要方法:
流程图:
以测试展示图为例,假设用户点击viewC后的处理流程
由是第一响应者的控件向系统传递
事件响应view→superView→rootVIew→viewController→window→Application→AppDelegate
说明示图:
输出的log 显示VC.nextUIResponder = VC.View.superView