iOS触摸事件的流动

原文链接:http://qingmo.me/2017/03/04/FlowOfUITouch/
欢迎关注我的微博:http://weibo.com/shellhue

当指肚轻触屏幕,整个系统像沉睡的生灵突然被惊醒,然后经历过腥风血雨的一段奇幻旅行,最终又归于沉寂。

整个iOS触摸事件从产生到寂灭大致如下图:

uitouchflow.png

起始阶段

----> cpu处于睡眠状态,等待事件发生
----> 手指触摸屏幕

系统响应阶段

----> 屏幕硬件感应到输入,并将感应到的事件传递给输入输出驱动IOKit
----> IOKit.framework封装整个触摸事件为IOHIDEvent对象
----> IOKit.framework通过IPC将事件转发给SpringBoard.app

以上是系统层的响应。系统感应到外界的输入,并将相应的输入封装成比较概括的IOHIDEvent对象,然后UIKit通过IOHIDEvent的类型,判断出相应事件应该由SpringBoard .app处理,直接通过mach port(IPC进程间通信)转发给SpringBoard.app。

SpringBoard.app就是iOS的系统桌面,当触摸事件发生时,也只有负责管理桌面的SpringBoard.app才知道如何正确的响应。因为触摸发生时,有可能用户正在桌面翻页找App,也有可能正处于在微信中刷朋友圈。

桌面响应阶段

----> SpringBoard.app主线程Runloop收到IOKit.framework转发来的消息苏醒,并触发对应Mach Port的Source1回调__IOHIDEventSystemClientQueueCallback()

----> 如果SpringBoard.app监测到有App在前台(记为xxxx.app),SpringBoard.app通过mach port(IPC进程间通信)转发给xxxx.app,如果SpringBoard.app监测到监测无前台App,则SpringBoard.app进入App内部响应阶段的第二段,记触发Source0回调。

App内部响应阶段

----> 前台App主线程Runloop收到SpringBoard.app转发来的消息苏醒,并触发对应Mach Port的Source1回调__IOHIDEventSystemClientQueueCallback()
----> Source1回调内部触发Source0回调__UIApplicationHandleEventQueue()
----> Soucre0回调内部,封装IOHIDEventUIEvent
----> Soucre0回调内部调用UIApplicationsendEvent:方法,将UIEvent传给UIWindow
----> 平时开发熟悉的触摸事件响应链从这开始了
----> 通过递归调用UIView层级的hitTest(_:with:),结合point(inside:with:)找到UIEvent中每一个UITouch所属的UIView(其实是想找到离触摸事件点最近的那个UIView)。这个过程是从UIView层级的最顶层往最底层递归查询,但这不是UIResponder响应链,事件响应是在UIEvent中每一个UITouch所属的UIView都确定之后方才开始。

但需要注意,以下三种情况UIViewhitTest(_:with:)不会被调用,也导致其子UIViewhitTest(_:with:)不会被调用,而之后响应事件是下向上传递的,这直接导致以下三种情况的UIView及其子UIView不接收任何触摸事件:

  1. userInteractionEnabled = NO
  2. hidden = YES
  3. alpha = 0.0~0.01之间

提示: UIImageView的userInteractionEnabled默认为NO,因此UIImageView以及它的子控件默认是不接收触摸事件的。

当把断点打在某个UIViewhitTest(_:with:)中时,对应的调用堆栈如下:

calltraceoftouching.png

----> 根据围绕UITouch所属的UIView及其祖先UIView的gesture recognizers,来确定一个UITouch的gestureRecognizers

----> UITouch所属的UIView和gestureRecognizers收到此UITouch和相应的UIEvent,并按照UITouch所处的状态调用四大UITouch方法touchesBegan(_:with:) touchesMoved(_:with:) touchesEnded(_:with:) touchesCancelled(_:with:)中的一个。(事件响应开始)

----> 对于UIView收到的UITouches事件(四大UITouch事件都是如此),则会按照UIResponder响应链一直往上传递,直到某个UIResponder因为主动响应触摸事件,切断了响应链(即不调用下一个UIResponder的响应方法),如果一直没有UIResponder做响应处理,则这些UITouches到达最后的响应者即UIApplication后,就被吃掉了,消失了。

----> 如果在事件响应过程中,有UIGestureRecognizer成功识别,则此UIGestureRecognizer将独自占有所需要的UITouches,这些UITouches所属的UIView及其他的UIGestureRecognizer的touchesCancelled(_:with:)方法将调用(如果在手势的代理中设置可以同时识别两个手势,则允许同时识别的手势均可以收到所需要的UITouches事件)。但与识别成功的UIGestureRecognizer无关的UITouches则会继续按照上述传递逻辑传递。也即允许两个手势同时识别,只要所占有的UITouches不相同。

----> 如果UIGestureRecognizer识别成功,则调用相应的action,处理对应的逻辑。如果某个UIResponder主动响应了触摸事件,则根据其本身的响应逻辑处理对应的业务,UIControl都是主动响应并切断UITouch的向上传递的。

----> UITouches事件流动完毕,整个系统重新进入睡眠等待下一个事件

总结

从手指触碰到屏幕,UITouch大致经历三个阶段,系统处理阶段---->SpringBoard.app处理阶段---->前台App处理阶段,事实上日常开发只需知晓最后一个阶段即可,前两个阶段参考资料也不多,更多的还涉及系统底层,这里仅做简单介绍。

欢迎关注我的微博:http://weibo.com/shellhue

参考文献:##

  1. 《iOS 事件处理机制与图像渲染过程》
  2. Event Handling Guide for iOS
  3. IOHIDFamily
  4. SpringBoard
  5. 深入理解RunLoop
  6. Programming iOS 9
  7. GSEvent
  8. 事件传递
  9. iOS事件点击之发生了什么?
  10. IOKit.framework
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容

  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 5,987评论 4 26
  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 56,546评论 51 597
  • 触摸事件iOS中的事件:在用户使用app过程中,会产生各种各样的事件。iOS中的事件可以分为3大类型 view的触...
    念念不忘一个丫头的容阅读 250评论 0 0
  • 本文介绍了iOS中使用频率较高的触摸事件,并阐述了事件产生和传递的过程,以及响应者链的事件传递过程 触摸事件 简介...
    搁浅的青蛙阅读 644评论 0 1
  • 触摸事件 iOS中的事件 在用户使用app过程中,会产生各种各样的事件 iOS中的事件可以分为3大类型:触摸事件,...
    SoManyDumb阅读 522评论 0 1