美文网首页iOS面试
iOS事件传递和响应机制

iOS事件传递和响应机制

作者: imzzb | 来源:发表于2019-06-12 17:23 被阅读0次

一部iOS设备会产生各种各样的事件(UIEvent 实例)比如:触摸屏幕、远程控制等,这些事件发生了就需要有响应者(UIResponder 实例)去响应这些事件。这就需要一套事件响应机制。

事件类型

查看UIEventType的定义,我们知道有4种事件类型。

typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches,
    UIEventTypeMotion,
    UIEventTypeRemoteControl,
    UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),
};

其中UIEventTypeTouches就是触摸手机屏幕产生的事件。UIEventTypeMotion我们能接触到的就可能是手机的shake,也就是摇晃事件了。UIEventTypeRemoteControlUIEventTypePresses对于手机App开发者一般遇不到。UIEventTypePresses的名字有一定的迷惑性,其实它指的是物理按键被按下,比如电视的遥控器。

除了UIEventTypeTouches其他事件我们都难以遇到。

事件响应者和响应链

能响应事件的都是UIResponder及其子类。常见的UIResponder的子类有:UIViewUIViewControllerUIApplicationUIApplicationDelegate

下面这张图是Apple官方文档中的图,可以看出事件的响应链与视图的层级关系基本一致。值得注意的是响应链的末端是...->UIWindow->UIApplication->UIApplicationDelegate。一个UIRespondernextResponder指向它的下一个响应者。你可以重写(override)nextResponder方法改变下一个响应者。实际上有些类已经重写了nextResponder,比如一个UIView如果是UIController的根视图,它的nextResponder会指向view controller。详见 Using Responders and the Responder Chain to Handle Events
Altering the Responder Chain一节。

事件响应链

如果顺着响应链没有发现能够响应事件的响应者,那么这个事件就会被忽略

我们看到,UIResponder中对应每种事件类型都有对应的事件响应方法,比如对于touch事件来说有touchesBegan: withEvent:,touchesMoved: withEvent:,touchesCancelled: withEvent:,touchesEnded: withEvent:,还有对于motion事件来说有motionBegan: withEvent:,motionEnded: withEvent:,motionCancelled: withEvent:。还有针对其他事件的方法,你可以去UIResponder类里去查看。

如果一个UIResponder子类重写(override)了上述所说事件响应方法,那么事件就算这个被这个类的实例响应了。事件就不再会沿着响应链传递。一个UIControl(UIButton是UIControl的子类),不管它有没有被增加一个target,事件传递到它这里就终止了。我猜UIControl内部实现了上面说的几个响应事件的方法。

比如一个UIView子类重写了touchesBegan: withEvent:,touchesMoved: withEvent:,touchesCancelled: withEvent:,touchesEnded: withEvent:,如果有触摸事件传递到这个子类的实例,就会调用这些方法,并停止向下传递。

事件传递机制

上面说的事件响应链有一个起点,这个起点叫做first responder。每一种事件都有找到或者指定first responder的规则,这里我们只关心触摸事件(touch event)。

当手机屏幕被触摸,系统将其包装成触摸事件(touch event)并传递给UIApplication,UIApplication传递给UIWindow(也是一个UIView的子类),UIWindow调用hitTest:withEvent:,得到一个能够响应触摸事件(touch event)的UIView。

UIViewhitTest:withEvent:方法,会遍历view的层级结构,找到能够响应这个事件的最深层的子视图,成为触摸事件的first responder。如果first responder不能响应事件,这个事件就会沿事件响应链传递直到被响应或者被忽略。

htiTest

上面的图片展示了hitTest:withEvent:是如何实现的。其中几个点我们需要注意,首先判断的是hidden,userInteractionEnable和alpha这几个属性,然后使用pointInside:withEvent:判断点击事件是否发生在该UIView内。然后是倒序遍历所有子视图并调用他们的hitTest:withEvent:方法。

事件传递机制原理的几个应用

1、非矩形可点击区域。比如一个button的一个圆形区域可以被点击,其他区域不可点击。只要重写pointInside:withEvent:,在圆形区域的点返回YES,不在圆形区域的返回NO。

2、按钮超出父视图。默认情况下,按钮超出父视图的部分是不可以点击的。我们可以重写父视图的pointInside:withEvent:方法,让按钮超出父视图的部分也返回YES。

参考:

1. Using Responders and the Responder Chain to Handle Events

相关文章

  • iOS之事件的传递和响应机制

    iOS之事件的传递和响应机制

  • 初识iOS事情处理机制

    参考:史上最详细的iOS之事件的传递和响应机制-原理篇iOS触摸事件全家桶史上最详细的iOS之事件的传递和响应机制...

  • 深入浅出iOS事件机制

    深入浅出iOS事件机制事件传递:响应链事件传递响应链

  • ios 事件传递和响应

    史上最详细的iOS之事件的传递和响应机制-原理篇iOS触摸事件传递响应之被忽视的手势识别器工作原理手势事件中can...

  • 01进阶之路-UI视图

    1. 事件传递机制和响应者链条 学习链接 事件传递机制iOS中的事件可以分为3大类型 1 触摸事件 2 加速计...

  • iOS事件传递和视图响应

    iOS事件响应机制的事件传递流程 - (UIView *)hitTest:(CGPoint)point withE...

  • 事件传递和响应机制

    iOS 事件传递和响应机制 一.概述 APPs通过responder objects来接收和处理点击事件,resp...

  • 响应者链

    史上最详细的iOS之事件的传递和响应机制Event Delivery: The Responder Chain

  • iOS 响应链

    iOS开发 - 事件传递响应链iOS 响应者链,事件的传递事件传递之响应链Cocoa Touch事件处理流程--响...

  • iOS事件传递和事件响应机制

    这里主要讲解记录下用户触摸点击手机屏幕后产生的事件是如何派发传递的,如何查找到适合响应事件的第一响应者控件,以及找...

网友评论

    本文标题:iOS事件传递和响应机制

    本文链接:https://www.haomeiwen.com/subject/vsngjftx.html