响应者链

来源:互联网 发布:1080p网络摄像头 编辑:程序博客网 时间:2024/04/30 03:22

一、app内

当发生事件响应时,必须知道由谁来响应事件。在iOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类,响应者链是一个由不同对象组成的层次结构,其中的每个对象将依次获得响应事件消息的机会。

比如,当你手指触摸屏幕后会发生以下事情:触摸事件被封装成一个UIEvent事件,去当前iOS操作系统的active app队列中取当前活跃的APP,把event传给它--->event

传给UIApplication--->

传给UIWindow的root view controller(rootVC)--->

调用rootVC.view的所有subviews的hitTest:event:方法。

哪个view的hitTest:event方法返回非nil值,则继续像该view的子视图传递,直到最顶端。顶端视图的hitTest:event返回非nil,并且处理了手势响应,则完成。否则没有处理,则向下传递。事件将沿着响应者链一直向下传递,直到被接受并做出处理。


二、特殊情况

不过如下情况,如果点击视图A的上半部分,会无法响应。因为超出了A的父视图的响应范围,响应链无法传递到A。


这时要重载A的父视图的hitTest:event方法:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    //  passHitToParentRect : 需要透传点击事件到父窗体的区域

    if (CGRectContainsPoint(self.passHitToParentRect, point)) {

        CGPoint pt = [self.showFromViewconvertPoint:pointfromView:self];

        return [self.showFromViewhitTest:ptwithEvent:event];

    }

    

    return [superhitTest:pointwithEvent:event];

}



三、硬件事件

      苹果注册了一个 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 事件都是在这个回调中完成的。




0 0