iOS 开发 Objective-C

iOS 底层 day30 iOS触摸事件

2020-10-22  本文已影响0人  望穿秋水小作坊

一、本节只记录问题,答案和细节从大神的文章中寻找

二、描述触摸事件的生命周期(从用户触碰屏幕开始)

1. 系统响应阶段

1.1 手指触碰屏幕,屏幕感受到触碰后,将事件交由 IOKit 处理。
1.2 IOKit 将触摸事件封装成IOHIDEvent 对象,并通过 mach port 传递给 SpringBoard 进程。

mach port 是 macOS 的 IPC 进程通信方式,各个进程之间通过它通信。
SpringBoard.app 是一个系统进程,可以理解为桌面系统,可以统一管理和分发系统收到的触摸事件。

1.3 SpringBoard 进程因接收到触摸事件,触发了主线程的 RunLoopsource1 事件源回调,会把事件传递给当前屏幕运行的 APP。(暂不讨论当前屏幕进程就是 Springboard 的情况)

2. APP响应阶段

2.1 Springboard 进程将事件通过 mach port 传递给当前 APP,会唤醒当前 APP 的 RunLoop 并且触发 source1 的回调。
2.2 source1 的回调又会触发 source0 的回调,source0 将事件封装成 UIEvent 对象,并且将触摸事件添加到 UIApplication 对象的事件队列中。
2.3 事件出队列后,开始了寻找最佳响应者的过程,这个过程又称为 hitTest 过程。
2.4 寻找到最佳响应者后,接下来 UIApplication 会调用 sendEvent: 将事件分发给最佳响应者
2.5 最佳响应者拿到事件后,可以决定对事件进行独自消化,也可以选择让事件在响应者链条中继续传递
2.6 触摸事件历经坎坷后要么被某个响应对象捕获后释放,要么致死也没能找到能够相应的对象,最终释放。至此,这个触摸事件的使命就算终结了,RunLoop 若没有其他事件需要处理,也将重归于眠,等待新的事件到来后唤醒。

三、UITouch 、 UIEvent、UIResponder 分别是什么?

1. UITouch

触摸的起源

2. UIEvent

事件的真身

3. UIResponder

一切都是为了满足它的野心

//手指触碰屏幕,触摸开始
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//手指在屏幕上移动
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//手指离开屏幕,触摸结束
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
//触摸结束前,某个系统事件中断了触摸,例如电话呼入
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

四、寻找事件的最佳响应者(hit-tested View)

1. 如何寻找最佳响应者?
2. 如何判断视图能否响应?

通过 hitTest:withEvent: 方法的返回值来判断:

3. hitTest:withEvent: 的内部实现?

五、事件的响应以及在响应链中的传递

1. 找到最佳响应者之后,事件是如何传递给最佳响应者的?
2. 什么是响应链?

最佳响应者首先接收到事件,然后便拥有了对事件的绝对控制权。它可以选择独吞这个事件,也可以将这个事件往下传递给其他响应者,这个由响应者构成的视图链就称之为响应链

六、总结

上一篇 下一篇

猜你喜欢

热点阅读