iOS 知识点 - 输入事件系统(UIKit 事件传递机制、响应链机制)

news/2025/12/5 17:30:42/文章来源:https://www.cnblogs.com/qisheng-blogs/p/19313087

iOS 事件系统全景图(硬件 → UIKit → 控件)

一个用户手指触摸屏幕的事件,从硬件到应用层,大致的经历是:

[ 触摸屏幕 ]↓
[ IOKit -> IOHIDEvent ] (硬件事件)↓
[ SpringBoard / BackBoard / SystemServer ] (系统事件中转)↓
[ UIApplication → RunLoop Source → _UIApplicationHandleEventQueue ] (App 事件入口)↓
[ UIKit 生成触摸序列 ] (UITouch / UIEvent)↓
[ UIWindow → UIView ] (事件传递机制: hitTest / pointInside)↓
[ UIGestureRecognizer ] (手势识别 / 状态机 / 冲突处理)↓
[ UIResponder ] (响应链: touchesBegan / nextResponder)↓
[ UIcontrol → Target-Action ] (控件事件)
模块 关键词 代表类
硬件输入系统 IOKit / HID / RunLoop Source
触摸事件系统 Touch / Phase / Event UITouch / UIEvent
事件传递机制 hitTest / pointInside UIView / UIWindow
手势识别机制 state / requireToFail / delegate UIGestureRecognizer 系列
响应链机制 nextResponder / touches UIResponder / UIViewController
控件事件系统 target-action / sendActions UIControl / UIButton
RunLoop驱动层(补充) CFRunLoopSource, Observer CFRunLoop, UIApplication

一、硬件输入系统

  • IOKit / HID 驱动 负责把物理触摸信号转成 IOHIDEvent;
  • 这些 IOHIDEventbackboardd 转发给前台进程(Your App);
  • 主线程 RunLoop 注册了 _UIApplicationHandleEventQueue() 作为输入源,接收事件。

二、触摸事件系统

iOS 的输入事件分为几种类型:

类型 描述 相关类
Touch 单指/多指触摸 UITouch
Press 按压 UIPress
Motion 摇一摇、重力加速度 UIEventSubtypeMotionShake
Remote Control 耳机线控 / 外设 UIEventSubtypeRemoteControl
  • 每一个手指都是一个 UITouch 实例,一次 触摸序列 对应一组 UITouchPhase
  • UIEvent 就是这些 touch 的容器。

1️⃣ 触摸序列(Touch Sequence)

  • 概念:一次连续的手指触碰屏幕到抬起(或取消)的整个过程。
  • 特点
    • 以手指为单位,每根手指对应一个 UITouch 对象;
    • 包含 一系列触摸阶段 (phase):
      touchesBegan → touchesMoved → touchesEnded / touchesCacelled
      
    • 对应系统内部的 唯一 touch identifier(保证每根手指的事件可以追踪)。

三、UIKit 分发层(事件传递机制)

UIKit 在接收到事件后开始做「命中检测」🎯

核心调用链 是:

UIApplication sendEvent: ↓
UIWindow sendEvent: // 从 window 开始↓
hitTest:withEvent:   // 做递归「命中检测」🎯↓
pointInside:withEvent:
  • hitTest: 规则(可交互条件):
    1. view.userInteractionEnabled == YES
    2. view.hidden == NO
    3. view.alpha > 0.01
    4. pointInside == YES
    
    • 倒序遍历 subviews,返回最上层命中的 view。
    • 将得到的 view 作为 First Responder 候选人。

四、手势识别层(UIGestureRecognizer 系列)

  • 核心思想:手势识别发生在 时间传递后、响应链前;手势识别器监听 触摸序列,根据预设规则判断是否满足手势条件。

每个手势识别器都有一套状态机和冲突调度逻辑(手势冲突)

状态机(UIGestureRecognizerState

状态 含义 触发时机
.Possible 初始状态 等待识别开始
.Began 识别开始 手势识别成功,手势开始响应
.Changed 手势进行中 位置/角度变化中
.Ended 识别完成 手势完成(抬手、离开)
.Cancelled 被系统或上层取消 如中断或手势冲突
.Failed 未识别成功 条件不满足(时间太短、移动太远)
  • 状态迁移 大致是:
Possible → Began → Changed → Ended→ Failed→ Cancelled

手势冲突与协调机制

多个手势可能同时附着在 同一视图/同一层级 上,系统需要协调 “谁可以先响应”。

  • 手势关系:每个 UIGestureRecognizer 都有一个「关系图」,由以下规则控制:
规则 方法 含义
失败依赖 requireGestureRecognizerToFail: 让某个手势必须等待另一个手势失败后再识别
同时识别 gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 允许多个手势同时识别
禁止识别 gestureRecognizer:shouldReceiveTouch: 完全忽略某次触摸
优先识别 gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer: 指定优先级关系
  • 优先级调度

    • 根据依赖关系构建「手势图」;
    • 同步触摸输入,驱动每个手势的状态机;
    • 当有手势识别成功后,让互斥手势进入 .Failed。
  • 举例:在 scrollview 上增加 tap 手势。

    [tap requireGestureRecognizerToFail:scrollView.panGestureRecognizer];
    
    • 表示「滚动优先于点击」;只有 pan 失败后,tap 才能触发。

手势与 Touch 的竞争关系

场景 结果
✅手势识别 success 手势回调触发,touches 系列不会再调用
❌手势识别 failure 事件进入响应链,触发 touches 系列方法(touchesBegan / Moved / Ended)
❌手势识别 cancel 调用touchesCancelled,touches 系列不会再调用

手势识别器接管 触摸序列 之后,UIKit 不会再把 touches 事件下发给视图层。


五、响应链机制(Responder Chain)

当手势识别失败后,触摸事件才能进入 UIResponder

1️⃣ 事件流向(子 -> 父)

image

1 - UIView→ 2 - UIViewController (若有)→ 3 - UIWindow→ 4 - UIApplication→ 5 - AppDelegate
  • 如果当前 responder 不处理事件,会传递给 nextResponder

六、控件事件系统(UIControl

UIControl → UIView → UIResponder → NSObject

UIKit 在响应链之上又封装了一层抽象机制:Target-Action

  • UIButton/UISwitch/UISlider 等继承自 UIControl
  • UIControl 通过 touches 系列方法 监控触摸,然后触发事件。

流程:

[ 触摸序列 → UIView (touchesBegan/Moved/Ended) ]↓[ UIControl (拦截触摸) ]↓判断事件类型↓[sendActionsForControlEvents:]↓执行注册的 Target-Action 回调

控件事件类型 (常用):

类型 时机
TouchDown 手指按下
TouchUpInside 在控件内抬起(最常用)
ValueChanged 值改变(Slider/Switch)

1️⃣ 在 UIScrollView 上的 UIButton 事件响应有延迟?

现象:

  • 点击按钮 → 高亮/触发 action 延迟约 100~200ms
  • 滑动触发滚动时,按钮点击可能被“吃掉”

原因分析

控件 事件处理机制
UIScrollView 内部有 UIPanGestureRecognizer 判断拖动;默认 delaysContentTouches = YES,会延迟将 touchesBegan 传给子控件
UIButton 依赖 touchesBegan/Moved/Ended 来管理高亮和触发 action;无法立即处理 touches,如果手势被占用,可能收到 touchesCancelled

✅ 核心点:

  • UIScrollView 先抢占触摸 → 拖动手势触发 → UIButton 延迟或取消事件。
  • UIButton 事件依赖 触摸序列未被取消 才能触发 target-action。

为什么 UIScrollView 先抢占触摸 ?

  • hitTest 结果
    • 手指点击在 UIButton 上 → 通过事件传递机制 → 设置 UIButtonFirst Responder 候选人
    • 但是 UIScrollView 内部的 panGestureRecognizer 也会监听同一触摸序列:
      • 手势识别器在 touchesBegan 延迟期间观察手势意图;
        • 如果 panGesture 成功,UIKit 会将触摸序列会被标记 “被 UIScrollView 占用” → UIButton 收到 touchesCancelled
        • 如果 panGesture 失败,触摸序列被 UIButton 占有。

这个延迟可以通过 UIScrollViewdelaysContentTouches 字段取消掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/988971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年深圳夹爪供应商哪家好?品牌选择指南

在深圳制造业自动化进程加速的2025年,柔性夹爪作为工业机器人末端执行器的核心部件,已成为解决异形、易碎、精密工件抓取难题的关键。苏州柔触机器人科技有限公司作为以柔性夹爪为核心的高科技企业,依托德国纳米材料…

2025年GEO优化实力厂家排行榜,谁主沉浮?GEO优化服务/GEO优化AI工具排名/广告全案策划、制作、发布GEO优化品牌哪家好

随着人工智能技术深度融入信息获取场景,GEO优化已成为企业品牌在数字时代构筑认知壁垒、抢占流量先机的关键战略。这一领域融合了地理定位的精准性与AI内容优化的智能性,旨在帮助品牌在主流AI工具的回答中占据有利位…

手写8000行代码构建完整AI训练推理流水线

前某中心联合创始人宣布其开源聊天机器人项目nanochat的8000行代码均为手动编写,未依赖AI编程工具。该项目提供了完整的训练与推理流水线,并引发了对AI泛化能力与当前技术局限的讨论。Andrej Karpathy 称 nanochat “…

如何进行iOS独立开发的市场推广?

iOS 独立开发的市场推广可围绕 App Store 内优化、多平台内容引流、付费广告加持、社群与口碑运营等多个维度推进,既能依托苹果官方渠道获取精准流量,也能通过低成本的内容和社群运营积累核心用户,以下是具体方案:…

2025年柔性夹爪选型指南:如何选择可靠的夹爪厂家

一、引言:聚焦柔性抓取技术的行业先锋——苏州柔触机器人科技有限公司 在智能制造加速推进的2025年,工业自动化对末端执行器的要求已从“能抓”向“精准、无损、柔性”跃升。作为这一趋势的重要推动者,苏州柔触机器…

rhel 9新特性

gcc 11 -- 默认c++ 17 glibc 2.34 python默认3.9 cgroup2默认启用 LLVM (13.0.1), Rust (1.58.1), and Go (1.17.1) 内核升级到5.14 默认jdk openjdk 17(redhat发行版)LightDB Enterprise Postgres--金融级关系型数…

rhel 9新特性

gcc 11 -- 默认c++ 17 glibc 2.34 python默认3.9 cgroup2默认启用 LLVM (13.0.1), Rust (1.58.1), and Go (1.17.1) 内核升级到5.14 默认jdk openjdk 17(redhat发行版)LightDB Enterprise Postgres--金融级关系型数…

2025数控刀片机械手厂家选型指南,品质厂家推荐

2025年,随着工业自动化向“智能协同”深度转型,数控刀片加工领域对自动化设备的精度、柔性与安全性要求愈发严苛。苏州柔触机器人科技有限公司作为以柔性夹爪为核心,专注于工业自动化柔性抓取解决方案的高科技企业,…

2025年圆形类工件柔性专业抓取厂商选型指南

一、引言:聚焦柔性抓取,柔触机器人引领智能制造新趋势 在工业自动化不断向高精度、高柔性演进的2025年,末端执行器作为机器人与工件直接交互的关键部件,其性能直接影响整条产线的效率与良率。苏州柔触机器人科技有…

Visual Studio 2026 Product Keys

Product Year Version Product Keys Visual Studio 2026 18.x Professional: NVTDK-QB8J9-M28GR-92BPC-BTHXK Enterprise: VYGRN-WPR22-HG4X3-692BF-QGT2Vhttps://x.com/massgravel/status/1988306014371008…

欢迎窗体

1 private async void buttonStartTask_Click(object sender, EventArgs e)2 {3 // 1. 实例化并显示加载窗体(非模态,以便后续操作)4 LoadingForm loadingForm = new LoadingForm();5 loadingForm.Star…

归程p4768

link 如果把所有互相之间的边没有积水的点看成一个个的块,显然块内部可以开车直接到达,也就是说块内部所有点的答案是一样的; 我们可以先用dij把每一个点到1号点的最短路预处理出来,建一棵kruskal重构树,然后在df…

html 和css基础常用的标签和样式(2)-css - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

计算粗心马虎纠正初中数学辅导精选:从根源培养严谨习惯,有效减少不必要的失分

初中数学计算中的“粗心马虎”,是困扰许多学生和家长的典型问题,往往导致考试中不必要的失分,甚至成为成绩提升的“隐形杀手”。值得注意的是,行业调研数据显示,超过60%的初中生在数学考试中因非知识性失误丢分,…

二极管三极管静态参数测试仪系统设备STD2000X--半导体领域和制造领域 - FORCREAT

半导体二极管三极管静态参数测试仪系统STD2000X能测很多电子元器件静态参数以及IV曲线扫描 如 Si, SiC, GaN 材料的 IGBTs,Diodes,MOSFETs,HEMT,BJTs,SCRs,光耦,继电器,稳压器...... 可以外接夹具、工装、探针…

2025年上海AI搜索结果优化渠道权威推荐榜单:上海AISEO机构/上海GEO关键词优化代运营/上海AI结果优化营销服务商综合评测

在信息爆炸与AI技术深度重塑搜索逻辑的今天,企业及品牌在数字世界中的“被发现能力”已成为商业竞争的关键一环。面对从百度、抖音到各类垂直AI平台的复杂算法生态,传统的搜索引擎优化(SEO)方法已难以适应。企业需…

完整教程:一篇最全Python 爬虫超详细讲解(零基础入门,适合小白)

完整教程:一篇最全Python 爬虫超详细讲解(零基础入门,适合小白)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &quo…

详细介绍:“AI+XR”赋能智慧研创中心:告别AI焦虑,重塑教师未来

详细介绍:“AI+XR”赋能智慧研创中心:告别AI焦虑,重塑教师未来2025-12-05 17:13 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !im…

昆明婚纱摄影店榜上的浪漫选择

一、评测对象概述 在昆明,婚纱摄影店众多,而位于西山区永昌街道环城南路好悦天地D区12楼的昆明乐派诗摄影服务有限公司备受瞩目。这是一家成立14年的原创型摄影工作室,拥有4000平沉浸式影像空间。 二、核心维度评测…

CAP博客集合

分布式事务,EventBus 解决方案:CAP【中文文档】 - Savorboard - 博客园 https://www.cnblogs.com/savorboard/p/cap-document.htmlCAP订阅模式详解:从基础订阅到分组订阅的完整方案-CSDN博客 https://blog.csdn.net…