当前位置: 首页 > news >正文

事件传递和响应者链

文章目录

  • 概述
  • UIEvent
  • UITouch
    • 手势识别器与Touch
  • UIResponder
  • 事件的传递
  • 第一响应者
    • 殴打视图直到它吐出靠前的视图(Hit-testing)
    • 响应者链
  • Target-Action 机制

概述

在使用手机的过程中,会产生很多的交互事件,如触摸屏幕,摇晃,按下按键,使用耳机等外接设备操控设备等,这些事件都需要系统去响应并处理,这篇文章简单将简单介绍系统如何响应,处理事件

UIEvent

UIEvent 描述用户与Apple的单次交互

应用可以接收不同类型的事件,包括触摸事件(touch events)、运动事件(motion events)、远程控制事件(remote-control events)和按下物理按键事件(press events)

触摸事件是最常见的事件,一般发送给触摸的视图

运动时间由UIKit触发,并与 Core Motion framework 运动事件进行区分

远程控制事件允许响应者对象接收外部设备的指令

按下按键代表软件可能与手柄或其他有物理按键设备的交互

触摸事件对象包含与事件相关的Touch,Touch Event对象包含一个或者多个UITouch对象

当发生触摸事件的时候,系统将事件交给合适的响应者,并调用touchesBegan(_:with:)方法,responder 提取 touch 中的数据,并作出适当响应

注意!!!

在更新触摸数据(即位置,面积等数据)时,UIKit会复用UIEvent对象

因此不要通过UIEvent 对象来读取你需要的数据,如果有必要使用UIEvent UITouch类的数据,应该在响应者方法中处理数据,并复制到自定义的数据结构里

UITouch

UIEvent 的介绍里,我们提到了多次UITouch 类对象,这里我们详细讲一下UITouch

UITouch对象表示屏幕上 touch 的位置、大小、移动和压力。

通过传递给 responder 的UIEvent来获取UITouch对象,UITouch提供以下信息:

  • touch 发生的 view 或 window
  • touch 位于 view 或 window 的位置
  • touch 大致半径
  • touch 压力大小(支持 3D Touch 或 Apple Pencil 的设备,悲哀的是 3D Touch由于各种奇奇怪怪的原因已经无了)

另外,touch 对象使用timestamp属性表示 touch 发生的时间,该时间为马赫时间。

另外的另外,timestamp记录的是事件发生(.began)、改变(.move)的时间,事件发生与传递可能有delay,使用时需对比前后事件的timestamp,而非UTC时间

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

整数类型的tapCount属性表示点击屏幕的次数,UITouch.Phase属性表示处于began、moved、ended、cancelled等阶段

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Touch 对象会在整个多点触控序列中存在。当处理多点触控序列时,可以引用 touch 对象,直到触控结束才释放。如果需要在多点触控序列外使用,需复制 touch 中的数据到自定义数据结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

estureRecognizers属性包含了当前处理 touch 的手势识别器。UIGestureRecognizer实现了touchesBegan(_:with:)touchesMoved(_:with)touchesEnded(_:with)touchesCancelled(_:with)四个方法

但它其并不是responder,也不参与响应链

在touch传递给view时,也会传递给view关联的gesture recognizer

如果view的父视图包含手势识别器,也会传递给父视图手势识别器。最终,传递给整个视图层级中的手势识别器

手势识别器与Touch

当touch首次创建并传递给gesture recognizer时,也会传递给hit-test视图,同时调用视图、手势识别器的touchesBegan(_:with:)方法

这样就不会因为手势识别器正在分析手势导致View接收不到时事件了。如果所有的手势识别器都识别失败,则视图会继续接收事件

如果一个View的手势识别器识别成功,会给view发送touchesCancelled(_:with:)消息,随后该view不会再收到该touch事件。可以通过修改cancelsTouchesInView属性为false可以改变这一特点

UIResponder

UIResponder类抽象了响应和处理事件的接口

响应者构成了事件处理的骨干,很多对象都继承于UIResponder ,如UIApplicationUIViewControllerUIView

当事件发生的时候,UIKit 调度事件给responder 处理

想要处理特定类型事件,响应者自身需要重写对应的方法

比较常见的有:

  • touchesBegan(_:with:)
  • touchesMoved(_:with:)
  • touchesEnded(_:with:)
  • touchesCancelled(_:with:)

响应者对象除了可以处理UIEvent ,还可以通过inputView 接收自定义的输入,系统的键盘就是一种inputView

当用户点击屏幕上的UITextField 的时候,他成为第一响应者并显示inputView默认展示系统键盘

你可以创建自定义的inputView来赋值给inputView属性,当其成为第一响应者时展示

事件的传递

这里讲一下当iPhone接收到一个事件的时候的处理过程,很多东西我自己也没全部理解,但是了解一下总归是好的

处理过程如下:

  1. 通过动作触发事件唤醒处于睡眠状态的App

  2. 使用IOKit.framework 将事件封装为 IOHIDEvent 对象

    IOKit.framework 是 Apple 操作系统的硬件中枢。它确保了操作系统能够识别、管理并与所有硬件设备高效、安全地通信。IOHIDEvent 中的 HID 代表 Human Interface Device

  3. 系统通过 mach port 将 IOHIDEvent 对象转发给 SpringBoard.app。

  4. SpringBoard.app 是 iOS 系统桌面 app,只接收按键、触摸、加速、接近传感器等几种 event。SpringBoard.app 找到可以响应这个事件的 app,并通过 mach port 将 IOHIDEvent 对象转发给 app 。

  5. app 主线程 RunLoop 接收到 SpringBoard.app 转发的消息,触发对应 mach port 的 source1 回调 __IOHIDEventSystemClientQueueCallback()。

  6. Source1 回调内部触发 Source0 回调 __UIApplicationHandleEventQueue()。

  7. Source0 回调内部,将 IOHIDEvent 对象转化为UIEvent

  8. Source0 回调内部调用 UIApplication 的sendEvent(_:)方法,将UIEvent发给UIWindow

UIWindow接收到事件后,开始传递事件。

第一响应者

第一响应者的概念在开发中是更为常见的一个概念

下图显示了包含UILabelUITextFieldUIButtonUIViewUIViewControllerUIWindow等视图的事件传递

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果文本框没有处理 event,UIKit 转发事件给文本框的父视图UIView,随后是控制器的根视图、视图控制器、window。如果 window 也没有处理 event,UIKit 转发 event 至 UIApplication

UIKit 根据事件类型指定第一响应者,事件类型如下:

事件类型第一响应者
触摸事件触摸的视图
按压事件焦点对象
晃动事件开发者或UIKit指定的对象
远程控制事件开发者或UIKit指定的对象
编辑按钮信息开发者或UIKit指定的对象

与加速度计、陀螺仪和磁力计相关的运动事件不跟随响应链。相反,Core Motion 会将这些事件直接传递给指定的对象。有关更多信息,请参阅 Core Motion Framework

触摸事件传递大致分为三个阶段:

  • 寻找触摸对象(通过击打测试)
  • 响应手势(手势识别器)
  • 触摸事件传递(响应者链)

我们接下来逐个讲解

殴打视图直到它吐出靠前的视图(Hit-testing)

Hit-testing 是查找 touch point 是否位于指定视图上的过程。iOS 使用 hit-testing 查找触摸事件最前的视图(即视图数组中 index 最大的视图),hit-testing 使用逆序深度优先遍历算法(reverse pre-order depth-first traversal algorithm)查找视图

在开始讲解击打测试之前,先看一下手指触摸屏幕到抬起的单次触摸流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以忽略其他的过程,我们现在只需要关注击打测试

注意到每次触摸屏幕,都会调用hit-testing,并且是在视图、gesture recognizer 收到UIEvent之前

Hit-testing 结束后,触摸位置下最前端视图被选为 first responder,它被关联到UITouch对象,并且 touch event 的所有阶段都会关联此视图

除了 hit test 视图,添加到 hit-test 视图上的视图、父视图上的手势识别器,都会关联到UITouch对象

最后,hit test 视图开始接受触摸系列事件

注意!!!

即使你的手指可能已经滑动到hit-test View的边界之外,到了另一个视图上,你的hit-Test View也会继续接收UITouch 直到你的touch-event结束

为了方便理解我们给出这么一个视图树,包括显示和视图层级树

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逆序深度优先遍历算法查找过程如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

先从根视图开始,先向UIWindow发送hitTest(_:with:)消息,该方法会返回包含触摸位置的视图

下图给出查找逻辑的流程图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

UIWindow 调用了自己的Hit-Test方法后,他会先判断自己是否可以被点击,主要检查三方面:

  • 自己是否可以被交互(userInteractionEnabled)
  • 自己是否可见(hidden和不透明度)
  • 触摸点是否在自己内部(pointInside:point方法)

在这些条件全部为真的时候,会遍历自己的子视图数组。由于后加入子视图数组的子视图的Z轴高度一定会高于先加入的(即addsubView逻辑,后加入的会被显示在靠前的位置),所以使用倒叙遍历

对每个遍历的子视图,会进行两个步骤

  1. 转换点坐标,将点的坐标转化为子视图的
  2. 对子视图递归调用hit-Test

递归调用后,新子视图会重复这个过程,即先进行自我检查,之后检查自己的子视图

手势识别器部分会在之后重新

响应者链

事件传递链是事件向下传递的方法,即依赖于hitTest:withEvent:pointInside:withEvent:

事件传递链为由上而下,即从UIApplication实例到最终视图UIView

最终视图即通过击打测试的视图,就是事件响应链开始

事件响应链决定链如果这个最终视图不想或者不能完全处理这个事件,事件应该向上传递给谁来处理

我们在之前的内容中提到了UIResponder 类,每一个UIResponder实例都有一个nextResponder属性,它指向链条中的下一个响应者,向上寻找最适合的响应对象

在实际应用上,我们会一般会重写touch:Begin方法,让响应者链断在合适的View(不调用super )

Target-Action 机制

UIButton 这类的控件,其Target-Action 机制也利用了响应者链,如果将target设置为nil,系统就会沿着响应者链查找第一个实现Action方法的响应者对象,并向其发送该消息

http://www.dtcms.com/a/561858.html

相关文章:

  • 07-神经元模型:介绍神经网络中神经元的结构和功能
  • 河南网站建设推广泰安招聘信息最新招聘2022
  • 第73题 矩阵置零
  • dw设计做网站案例使用免费的代码做网站
  • C++11新特性学习
  • 手机网站php源码网站建设课设心得
  • 网站年龄和域名年龄软件开发流程八个步骤模板
  • mybatis类型转换器
  • Vue项目中的Electron桌面应用开发实践指南
  • 如何运行asp.net网站wordpress怎么导入demo文件
  • focusPolicy/setFocusPolicy(FocusPolicy),styleSheet
  • 六.DockerFile解析及其应用部署
  • wp企业网站模板数据分析师事务所
  • AWS DMS 大规模数据库迁移:完全加载+持续复制最佳实践
  • 阿里巴巴六边形架构-从解耦到可测试的架构设计利器
  • 中国世界排名前500大学seo网上培训多少钱
  • 做网站做哪个行业好商城网站建设高端
  • 正规网站建设建设公司雅安建设局网站
  • 如何在Java中整合Redis?
  • 官方网站是什么意思免费链接生成器
  • 增加网站访客珠宝首饰商城网站建设
  • 网络通信的奥秘:TCP与UDP详解(三)
  • 理财网站开发最近中国新闻
  • 详解网络安全免杀对抗:攻防的猫鼠游戏
  • 【开题答辩全过程】以 高考志愿分析系统为例,包含答辩的问题和答案
  • ESP-IDF基础入门(2)
  • 中国建设官方网站首页网上商城推广方案
  • 网站建设必须安装程序天眼查公司信息查询
  • 织梦网站首页是哪个文件网站手机访问跳转代码
  • 博弈dp|凸包|math分类