一.响应链
简单来说包括两方面:1.事件传递 2.处理响应
二.事件传递
- 点击屏幕
- UIApplication
- UIWindow
- 调用
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
判断那个view应该处理这个事件
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
内部实现
1.for循环拿到所有子视图,越后面添加的越先判断
2.如果isHidden=YES
或者userInteractionEnabled=NO
或者alpha<0.01
返回nil
3.调用- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
三.处理响应
找到点击的view后,来到了响应者链
- 该view处理事件
- 如果view不处理,那么将事件发送给它的父视图
- 父视图的viewcontroller
- UIVindow
- UIApplication
- Delegate
- 丢弃该事件
更加详细
苹果注册了一个 Source1 (基于 mach port 的) 用来接收系统事件,其回调函数为 __IOHIDEventSystemClientQueueCallback()。
当一个硬件事件(触摸/锁屏/摇晃等)发生后,首先由 IOKit.framework 生成一个 IOHIDEvent 事件并由 SpringBoard 接收。这个过程的详细情况可以参考这里。SpringBoard 只接收按键(锁屏/静音等),触摸,加速,接近传感器等几种 Event,随后用 mach port 转发给需要的App进程。随后苹果注册的那个 Source1 就会触发回调,并调用 _UIApplicationHandleEventQueue() 进行应用内部的分发。
_UIApplicationHandleEventQueue() 会把 IOHIDEvent 处理并包装成 UIEvent 进行处理或分发,其中包括识别 UIGesture/处理屏幕旋转/发送给 UIWindow 等。通常事件比如 UIButton 点击、touchesBegin/Move/End/Cancel 事件都是在这个回调中完成的。
网友评论