事件类型
iOS的事件可以分为三类:触摸事件,加速计事件,远程控制事件
iOS中不是任何对象都能处理对象,只有继承了UIResponder的对象才能接收并处理事件. ---->响应者对象
typedef NS_ENUM(NSInteger, UIEventType) {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
};
//事件类型
@property(nonatomic,readonly) UIEventType type
@property(nonatomic,readonly) UIEventSubtype subtype
//事件产生的时间
@property(nonatomic,readonly) NSTimeInterval timestamp;
事件的传递
-
系统把事件加入到一个由UIApplication管理的事件队列中
之所以加入队列而不是栈是因为队列先进先出,意味着先产生的事件,先处理 -
然后,事件会按照UIApplication -> UIWindow -> SuperView -> SubView的顺序不断的检测
-
而检测就是靠两个方法hitTest与pointInside
事件与runloop
当我们触发了事件(触摸/锁屏/摇晃等)后,
-
由
IOKit.framework
生成一个IOHIDEvent
事件 -
而
IOKit
是苹果的硬件驱动框架 -
由它进行底层接口的抽象封装与系统进行交互传递硬件感应的事件
-
它专门处理用户交互设备,由
IOHIDServices
和IOHIDDisplays
两部分组成 -
其中
IOHIDServices
是专门处理用户交互的,它会将事件封装成IOHIDEvents
对象,详细请看这里 -
然后这些事件又由SpringBoard接收,它只接收收按键(锁屏/静音等),触摸,加速,接近传感器等几种 Event
-
接着用
mach port
转发给需要的App进程 -
Source1
接收IOHIDEvent,之后再回调__IOHIDEventSystemClientQueueCallback()内触发的Source0 -
Source0
再触发的__dispatchPreprocessEventFromEventQueue()
。 -
__dispatchPreprocessEventFromEventQueue()
把IOHIDEvent
处理包装成UIEvent
进行处理分发,我们平时的UIGesture/处理屏幕旋转/发送给 UIWindow/UIButton 点击、touchesBegin/Move/End/Cancel这些事件,都是在这个回调中完成。
0 - [AView touchesBegan:withEvent
1 - [UIWindow _sendTouchesForEvent]
2 - [UIWindow sendEvent]
3 - [UIApplication sendEvent]
4 __dispatchPreprocessEventFromEventQueue
5 __handleEventQueueInternal
6 _CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION_
7 _CFRunLOOPDoSource0
8 _CFRunLOOPDoSources1
9 _CFRunLoopRun
10 _CFRunLoopRunSpecific
11 GSEventRunModal
12 UIApplication
13 main
14 start
手势识别
-
当上面的 __dispatchPreprocessEventFromEventQueue() 识别了一个手势时,其首先会调用 Cancel 将当前的 touchesBegin/Move/End 系列回调打断。随后系统将对应的 UIGestureRecognizer 标记为待处理。
-
苹果注册了一个 Observer 监测 BeforeWaiting (Loop即将进入休眠) 事件,这个Observer的回调函数是 _UIGestureRecognizerUpdateObserver(),其内部会获取所有刚被标记为待处理的 GestureRecognizer,并执行GestureRecognizer的回调。
-
当有 UIGestureRecognizer 的变化(创建/销毁/状态改变)时,这个回调都会进行相应处理。
网友评论