iOS觸摸事件的流動(dòng)

原文鏈接:http://qingmo.me/2017/03/04/FlowOfUITouch/
歡迎關(guān)注我的微博:http://weibo.com/shellhue

當(dāng)指肚輕觸屏幕,整個(gè)系統(tǒng)像沉睡的生靈突然被驚醒,然后經(jīng)歷過腥風(fēng)血雨的一段奇幻旅行绒疗,最終又歸于沉寂宏蛉。

整個(gè)iOS觸摸事件從產(chǎn)生到寂滅大致如下圖:

uitouchflow.png

起始階段

----> cpu處于睡眠狀態(tài)恼除,等待事件發(fā)生
----> 手指觸摸屏幕

系統(tǒng)響應(yīng)階段

----> 屏幕硬件感應(yīng)到輸入,并將感應(yīng)到的事件傳遞給輸入輸出驅(qū)動(dòng)IOKit
----> IOKit.framework封裝整個(gè)觸摸事件為IOHIDEvent對象
----> IOKit.framework通過IPC將事件轉(zhuǎn)發(fā)給SpringBoard.app

以上是系統(tǒng)層的響應(yīng)曼氛。系統(tǒng)感應(yīng)到外界的輸入豁辉,并將相應(yīng)的輸入封裝成比較概括的IOHIDEvent對象,然后UIKit通過IOHIDEvent的類型搪锣,判斷出相應(yīng)事件應(yīng)該由SpringBoard .app處理秋忙,直接通過mach port(IPC進(jìn)程間通信)轉(zhuǎn)發(fā)給SpringBoard.app。

SpringBoard.app就是iOS的系統(tǒng)桌面构舟,當(dāng)觸摸事件發(fā)生時(shí)灰追,也只有負(fù)責(zé)管理桌面的SpringBoard.app才知道如何正確的響應(yīng)堵幽。因?yàn)橛|摸發(fā)生時(shí),有可能用戶正在桌面翻頁找App弹澎,也有可能正處于在微信中刷朋友圈朴下。

桌面響應(yīng)階段

----> SpringBoard.app主線程Runloop收到IOKit.framework轉(zhuǎn)發(fā)來的消息蘇醒,并觸發(fā)對應(yīng)Mach Port的Source1回調(diào)__IOHIDEventSystemClientQueueCallback()苦蒿。

----> 如果SpringBoard.app監(jiān)測到有App在前臺(tái)(記為xxxx.app)殴胧,SpringBoard.app通過mach port(IPC進(jìn)程間通信)轉(zhuǎn)發(fā)給xxxx.app,如果SpringBoard.app監(jiān)測到監(jiān)測無前臺(tái)App佩迟,則SpringBoard.app進(jìn)入App內(nèi)部響應(yīng)階段的第二段团滥,記觸發(fā)Source0回調(diào)。

App內(nèi)部響應(yīng)階段

----> 前臺(tái)App主線程Runloop收到SpringBoard.app轉(zhuǎn)發(fā)來的消息蘇醒报强,并觸發(fā)對應(yīng)Mach Port的Source1回調(diào)__IOHIDEventSystemClientQueueCallback()灸姊。
----> Source1回調(diào)內(nèi)部觸發(fā)Source0回調(diào)__UIApplicationHandleEventQueue()
----> Soucre0回調(diào)內(nèi)部,封裝IOHIDEventUIEvent
----> Soucre0回調(diào)內(nèi)部調(diào)用UIApplicationsendEvent:方法秉溉,將UIEvent傳給UIWindow
----> 平時(shí)開發(fā)熟悉的觸摸事件響應(yīng)鏈從這開始了
----> 通過遞歸調(diào)用UIView層級(jí)的hitTest(_:with:)力惯,結(jié)合point(inside:with:)找到UIEvent中每一個(gè)UITouch所屬的UIView(其實(shí)是想找到離觸摸事件點(diǎn)最近的那個(gè)UIView)。這個(gè)過程是從UIView層級(jí)的最頂層往最底層遞歸查詢召嘶,但這不是UIResponder響應(yīng)鏈父晶,事件響應(yīng)是在UIEvent中每一個(gè)UITouch所屬的UIView都確定之后方才開始。

但需要注意弄跌,以下三種情況UIViewhitTest(_:with:)不會(huì)被調(diào)用甲喝,也導(dǎo)致其子UIViewhitTest(_:with:)不會(huì)被調(diào)用,而之后響應(yīng)事件是下向上傳遞的铛只,這直接導(dǎo)致以下三種情況的UIView及其子UIView不接收任何觸摸事件:

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

提示: UIImageView的userInteractionEnabled默認(rèn)為NO,因此UIImageView以及它的子控件默認(rèn)是不接收觸摸事件的俺猿。

當(dāng)把斷點(diǎn)打在某個(gè)UIViewhitTest(_:with:)中時(shí),對應(yīng)的調(diào)用堆棧如下:

calltraceoftouching.png

----> 根據(jù)圍繞UITouch所屬的UIView及其祖先UIView的gesture recognizers格仲,來確定一個(gè)UITouch的gestureRecognizers

----> UITouch所屬的UIView和gestureRecognizers收到此UITouch和相應(yīng)的UIEvent,并按照UITouch所處的狀態(tài)調(diào)用四大UITouch方法touchesBegan(_:with:) touchesMoved(_:with:) touchesEnded(_:with:) touchesCancelled(_:with:)中的一個(gè)诵冒。(事件響應(yīng)開始)

----> 對于UIView收到的UITouches事件(四大UITouch事件都是如此)凯肋,則會(huì)按照UIResponder響應(yīng)鏈一直往上傳遞,直到某個(gè)UIResponder因?yàn)橹鲃?dòng)響應(yīng)觸摸事件汽馋,切斷了響應(yīng)鏈(即不調(diào)用下一個(gè)UIResponder的響應(yīng)方法)侮东,如果一直沒有UIResponder做響應(yīng)處理,則這些UITouches到達(dá)最后的響應(yīng)者即UIApplication后豹芯,就被吃掉了悄雅,消失了。

----> 如果在事件響應(yīng)過程中铁蹈,有UIGestureRecognizer成功識(shí)別宽闲,則此UIGestureRecognizer將獨(dú)自占有所需要的UITouches,這些UITouches所屬的UIView及其他的UIGestureRecognizer的touchesCancelled(_:with:)方法將調(diào)用(如果在手勢的代理中設(shè)置可以同時(shí)識(shí)別兩個(gè)手勢,則允許同時(shí)識(shí)別的手勢均可以收到所需要的UITouches事件)容诬。但與識(shí)別成功的UIGestureRecognizer無關(guān)的UITouches則會(huì)繼續(xù)按照上述傳遞邏輯傳遞娩梨。也即允許兩個(gè)手勢同時(shí)識(shí)別,只要所占有的UITouches不相同览徒。

----> 如果UIGestureRecognizer識(shí)別成功狈定,則調(diào)用相應(yīng)的action,處理對應(yīng)的邏輯习蓬。如果某個(gè)UIResponder主動(dòng)響應(yīng)了觸摸事件纽什,則根據(jù)其本身的響應(yīng)邏輯處理對應(yīng)的業(yè)務(wù),UIControl都是主動(dòng)響應(yīng)并切斷UITouch的向上傳遞的躲叼。

----> UITouches事件流動(dòng)完畢芦缰,整個(gè)系統(tǒng)重新進(jìn)入睡眠等待下一個(gè)事件

總結(jié)

從手指觸碰到屏幕,UITouch大致經(jīng)歷三個(gè)階段押赊,系統(tǒng)處理階段---->SpringBoard.app處理階段---->前臺(tái)App處理階段饺藤,事實(shí)上日常開發(fā)只需知曉最后一個(gè)階段即可,前兩個(gè)階段參考資料也不多流礁,更多的還涉及系統(tǒng)底層涕俗,這里僅做簡單介紹。

歡迎關(guān)注我的微博:http://weibo.com/shellhue

參考文獻(xiàn):##

  1. 《iOS 事件處理機(jī)制與圖像渲染過程》
  2. Event Handling Guide for iOS
  3. IOHIDFamily
  4. SpringBoard
  5. 深入理解RunLoop
  6. Programming iOS 9
  7. GSEvent
  8. 事件傳遞
  9. iOS事件點(diǎn)擊之發(fā)生了什么神帅?
  10. IOKit.framework
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末再姑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子找御,更是在濱河造成了極大的恐慌元镀,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霎桅,死亡現(xiàn)場離奇詭異栖疑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滔驶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門遇革,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揭糕,你說我怎么就攤上這事萝快。” “怎么了著角?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵揪漩,是天一觀的道長。 經(jīng)常有香客問我吏口,道長奄容,這世上最難降的妖魔是什么冰更? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮嫩海,結(jié)果婚禮上冬殃,老公的妹妹穿的比我還像新娘。我一直安慰自己叁怪,他們只是感情好审葬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奕谭,像睡著了一般涣觉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上血柳,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天官册,我揣著相機(jī)與錄音,去河邊找鬼难捌。 笑死膝宁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的根吁。 我是一名探鬼主播员淫,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼击敌!你這毒婦竟也來了介返?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤沃斤,失蹤者是張志新(化名)和其女友劉穎圣蝎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衡瓶,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡徘公,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哮针。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片步淹。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖诚撵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情键闺,我是刑警寧澤寿烟,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站辛燥,受9級(jí)特大地震影響筛武,放射性物質(zhì)發(fā)生泄漏缝其。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一徘六、第九天 我趴在偏房一處隱蔽的房頂上張望内边。 院中可真熱鬧,春花似錦待锈、人聲如沸漠其。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽和屎。三九已至,卻和暖如春春瞬,著一層夾襖步出監(jiān)牢的瞬間柴信,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工宽气, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留随常,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓萄涯,卻偏偏與公主長得像绪氛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子窃判,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在iOS開發(fā)中經(jīng)常會(huì)涉及到觸摸事件钞楼。本想自己總結(jié)一下,但是遇到了這篇文章袄琳,感覺總結(jié)的已經(jīng)很到位询件,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,010評論 4 26
  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的唆樊?困惑于Cell怎么突然不能點(diǎn)擊了宛琅?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求?亦或是...
    Lotheve閱讀 57,082評論 51 599
  • 觸摸事件iOS中的事件:在用戶使用app過程中逗旁,會(huì)產(chǎn)生各種各樣的事件嘿辟。iOS中的事件可以分為3大類型 view的觸...
  • 本文介紹了iOS中使用頻率較高的觸摸事件,并闡述了事件產(chǎn)生和傳遞的過程片效,以及響應(yīng)者鏈的事件傳遞過程 觸摸事件 簡介...
    擱淺的青蛙閱讀 652評論 0 1
  • 觸摸事件 iOS中的事件 在用戶使用app過程中红伦,會(huì)產(chǎn)生各種各樣的事件 iOS中的事件可以分為3大類型:觸摸事件,...
    SoManyDumb閱讀 525評論 0 1