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

iOS的传递链与响应链机制

iOS的框架分为:应用层、触摸层、媒体层、核心服务层、核心系统操作层以及内核和驱动层。

详见https://blog.csdn.net/ScheenDuan/article/details/134274203?spm=1001.2014.3001.5501

其中触摸事件涉及到触摸层中的UIKit中的UIResponse,只有继承了UIResponse的对象才能接受处理事件。

一、事件传递链(命中测试):

事件传递链用于确定哪个视图应该接收用户触摸或手势事件。当用户与界面发生交互时,系统会沿着视图层次结构从上到下传递触摸事件,并最终找到能够处理该事件的最小子视图。这个过程称为 Hit-Testing,即事件命中测试。

在 iOS 世界中,为了确定视图是否可以与用户交互,视图具有一个名为
hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? 的方法,一旦有来自用户的触摸事件,系统将调用此函数来告诉视图是否应该触发触摸事件或手势识别器。

这里先介绍这个相关方法:

  1. hitTest(_:with:):通过递归调用来确定哪个子视图最终应该接收触摸事件。
  2.  pointInside(_:with:):当系统需要确定某个触摸点是否在某个视图内时,会调用 pointInside(_:with:)。如果返回 true,表示点在视图内;如果返回 false,则表示点不在视图内。pointInside 只检查当前视图的边界,而不涉及子视图。

这两个方法是包含关系,见如下代码:

func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {// 检查触摸点是否在当前视图内if !point(inside: point, with: event) {return nil}if alpha < 0.01 || !isUserInteractionEnabled || isHidden {return nil}// 遍历子视图并递归查找最合适的响应视图for subview in subviews.reverse() {if let hitView = subview.hitTest(point, with: event) {return hitView}}return nil
}

具体的事件传递过程:

1. 事件的触发

• 当用户触摸屏幕时,系统会首先将触摸事件封装为 UIEvent 对象,传递给应用的窗口对象(UIWindow)。

2. UIWindow 开始传递

• UIWindow 会调用 hitTest(_:with:) 方法,通过事件位置查找出最适合接收触摸事件的视图。这通常是视图层次结构中的最小的子视图(也称为“命中的视图”)。

3. 视图层次结构中的传递

• hitTest(_:with:) 从根视图开始,递归检查每个子视图,使用 pointInside(_:with:) 方法判断触摸点是否在某个视图内。

• 找到合适的子视图后,它将作为事件的最终处理者。

4. 处理事件

• 如果视图对象能够处理事件,它会响应相关的事件处理方法,如 touchesBegan(_:with:)、touchesMoved(_:with:) 或 touchesEnded(_:with:)。

5. 未处理事件的传递

• 如果视图不能处理事件,或者选择不处理事件,它会将事件传递给其下一个响应者(next responder)。

• 这个传递过程会沿着响应链向上传递,最终可能传递到视图控制器(UIViewController)、父视图、窗口(UIWindow)、应用程序对象(UIApplication),甚至是系统对象。

总的来说,就是触摸了就生成一个事件,然后事件从父视图传递给子视图(寻找合适的响应视图),在这期间是用hitest方法去递归查找并且配合了point inside函数查看是否响应在了视图的边界范围内,当找到最适合的响应视图后,才会触发类似于touchesBegan之类的事件处理方法。

提一嘴,如果触摸点在视图外的话怎么进行处理?

  1. 通过重写 pointInside(_:with:) 方法,手动扩展视图的可交互区域。
  2. 在父视图中手动处理事件。
  3. 通过手势识别器或控制器全局捕获触摸事件。
  4. 在 UIViewController 级别处理触摸事件。
  5. 通过响应链将事件传递给下一个响应者。

二、响应链

响应链与事件的实际处理有关。当一个视图或控件接收到触摸事件之后,如果它不能处理该事件,它会将事件沿着 响应链 传递给其他对象(如其父视图或控制器)进行处理。响应链是基于 UIResponder 类实现的。

响应链的流程:

传递顺序:当一个对象无法处理事件时,事件会传递给它的下一个响应者(即 nextResponder)。如果下一个响应者也无法处理事件,则事件继续向上传递,直到到达根响应者(通常是 UIApplication 或 UIWindow)。

• nextResponder:每个 UIResponder 都有一个 nextResponder 属性,指向下一个响应者(通常是视图的父视图、视图控制器等)。

响应链的流程示例:

1. 用户点击按钮,但按钮没有处理事件。

2. 按钮会将事件传递给其父视图,父视图再传递给 UIViewController。

3. 如果 UIViewController 也不能处理,事件会传递给 UIWindow,最后传递给 UIApplication。

总的来说:响应链关注的是事件的“处理”过程,即当一个对象无法处理事件时,它将事件传递给谁。它提供了一个灵活的机制,使得即使某个控件无法处理事件,事件也可以通过 nextResponder 传递给其他对象进行处理。

传递链和响应链区别:

  • 事件传递链决定了谁接收事件,负责从顶层到子视图逐层传递事件。
  • 响应链则决定了谁处理事件,如果接收事件的视图无法处理,它可以将事件传递给下一个响应者。

参考:https://slk11075.medium.com/hittest-on-ios-ec3b869b57f9

不用但一定要懂 ---- iOS 之 响应链、传递链 与 手势识别_ios手势响应链-CSDN博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CSP-J算法基础 树状结构与二叉树
  • 学习笔记 - 知识图谱的符号表示方法
  • C#中的装箱和拆箱是什么
  • Sentinel 控制界面
  • element form rules 验证数组对象属性时如何写判断规则
  • 组合总和IV(力扣---动态规划)
  • 多态(上)【C++】
  • 如何搞定日语翻译?试试这四款工具
  • FreeRTOS学习(2)延时函数的封装
  • 【白话树】之 树的基本知识、存储结构和二叉树转换
  • MySQL 子查询
  • hiresfix_latent 使用Upscale放大节点 对图片进行放大Comfyui
  • 众店绿色积分模式:引领消费新风尚,共筑商业新生态
  • 研1日记10
  • 深入探索系统架构设计
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • 07.Android之多媒体问题
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • CSS盒模型深入
  • httpie使用详解
  • Mocha测试初探
  • opencv python Meanshift 和 Camshift
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • spring + angular 实现导出excel
  • Vue 2.3、2.4 知识点小结
  • 开源SQL-on-Hadoop系统一览
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 手机端车牌号码键盘的vue组件
  • 跳前端坑前,先看看这个!!
  • ​520就是要宠粉,你的心头书我买单
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #微信小程序:微信小程序常见的配置传旨
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (13)Hive调优——动态分区导致的小文件问题
  • (3) cmake编译多个cpp文件
  • (AngularJS)Angular 控制器之间通信初探
  • (C++17) optional的使用
  • (el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程
  • (WSI分类)WSI分类文献小综述 2024
  • (多级缓存)多级缓存
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (十八)Flink CEP 详解
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (一)kafka实战——kafka源码编译启动
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .JPG图片,各种压缩率下的文件尺寸