iOS事件傳遞鏈, 響應(yīng)鏈

傳遞鏈

  • 傳遞鏈: Application -> window -> root view -> ... -> first view
  • UIResponse:響應(yīng)對象的基類钙态,定義了事件處理的接口
    • 常見的子類: UIView,UIViewController氮双,UIApplication以及所有繼承自UIView的UIKit類都直接或間接的繼承自UIResponder
  • 藍(lán)色箭頭為事件的傳遞過程瞎饲,紅色箭頭為事件響應(yīng)的過程
  • 當(dāng)發(fā)生點(diǎn)擊事件后,系統(tǒng)會(huì)將事件加入到UIApplication管理的一個(gè)任務(wù)隊(duì)列中
  • UIApplication將處于任務(wù)隊(duì)列最前端的事件向下分發(fā)給UIWindow
  • UIWindow將事件向下分發(fā)給View
  • UIView首先看自己是否能夠處理事件,觸摸點(diǎn)擊是否在自己身上卦洽,如果能,那么繼續(xù)尋找子視圖(遞歸天添加順序)
  • 遍歷子控件斜棚,重復(fù)以上兩步
  • 如果沒有找到阀蒂,那么window自己就是事件處理
  • 如果自己不能處理,那么不做任何處理
  • 事件傳遞的兩個(gè)核心方法
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool
  • hitTest方法用來尋找哪一個(gè)視圖來響應(yīng)這個(gè)事件
  • point(inside方法用來判斷某一個(gè)點(diǎn)擊的位置是否在視圖范圍內(nèi)弟蚀,如果在返回true
  • View不接受事件處理的情況有:
    • alpha < 0.01
    • userInteractionEnable = false
    • hidden = true
    • 超出父控件響應(yīng)區(qū)域
事件傳遞流程
  • 點(diǎn)擊屏幕產(chǎn)生觸摸事件蚤霞,系統(tǒng)將這個(gè)事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中,UIApplication會(huì)從消息隊(duì)列里取事件分發(fā)下去义钉,首先傳給UIWindow
  • 在UIWindow中就會(huì)調(diào)用hitTest:withEvent:方法去返回一個(gè)最終響應(yīng)的視圖
  • 在hitTest:withEvent:方法中就會(huì)去調(diào)用pointInside: withEvent:去判斷當(dāng)前點(diǎn)擊的point是否在UIWindow范圍內(nèi)昧绣,如果是的話,就會(huì)去遍歷它的子視圖來查找最終響應(yīng)的子視圖
  • 遍歷的方式是使用倒序的方式來遍歷子視圖捶闸,也就是說最后添加的子視圖會(huì)最先遍歷夜畴,在每一個(gè)視圖中都回去調(diào)用它的hitTest:withEvent:方法,可以理解為是一個(gè)遞歸調(diào)用
  • 最終會(huì)返回一個(gè)響應(yīng)視圖删壮,如果返回視圖有值斩启,那么這個(gè)視圖就作為最終響應(yīng)視圖,結(jié)束整個(gè)事件傳遞醉锅;如果沒有值兔簇,那么就會(huì)將UIWindow作為響應(yīng)者
  • 傳遞鏈?zhǔn)怯脕慝@取到一個(gè)響應(yīng)控件(第一響應(yīng)者)

響應(yīng)鏈

  • 自底向上傳遞
  • 傳遞鏈獲取獲取到了第一響應(yīng)者,接下來就開始響應(yīng)事件
  • 響應(yīng)鏈: first view -> super view -> ... -> view controller -> window -> application -> appdelegate
  • 找到最適合的響應(yīng)視圖后事件會(huì)從此視圖開始沿著響應(yīng)鏈nextResponder傳遞,直到找到處理事件的視圖,如果沒有處理的事件會(huì)被丟棄垄琐。
  • 如果視圖有父視圖則nextResponder指向父視圖
  • 如果是根視圖則指向控制器边酒,最終指向AppDelegate, 他們都是通過重寫nextResponder來實(shí)現(xiàn)
響應(yīng)傳遞示例
  • 如果label不處理事件,UIKit 將事件發(fā)送到label的父視圖view
  • 如果view不處理事件狸窘,則將事件發(fā)送給super view
  • 如果superview不處理事件墩朦,繼續(xù)層層查找,直到根視圖翻擒,根視圖的nextResponder指向ViewController
  • 如果viewController不處理事件氓涣,則將事件傳遞給window
  • 如果window不處理事件,則將事件傳遞給UIApplication
  • UIApplication不處理事件陋气,則將事件傳遞給Appdelegate
  • 如果都沒有找到合適的對象處理劳吠,則事件被拋棄

應(yīng)用

  • 利用響應(yīng)鏈獲取view的控制器
extension UIView {
    var viewController: UIViewController? {
        var next = next
        var current: UIViewController?
        while next != nil {
            if next is UIViewController {
                return next as? UIViewController
            }
            next = next?.next
        }
        return current
    }
}
  • 指定按鈕的點(diǎn)擊范圍
  • 修復(fù)子視圖超出父視圖無法點(diǎn)擊
  • 兩個(gè)覆蓋的button,分別響應(yīng)不同的事件
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巩趁,一起剝皮案震驚了整個(gè)濱河市痒玩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌议慰,老刑警劉巖蠢古,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異别凹,居然都是意外死亡草讶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門炉菲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堕战,“玉大人,你說我怎么就攤上這事颁督。” “怎么了浇雹?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵沉御,是天一觀的道長。 經(jīng)常有香客問我昭灵,道長吠裆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任烂完,我火速辦了婚禮试疙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抠蚣。我一直安慰自己祝旷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怀跛,像睡著了一般距贷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吻谋,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天忠蝗,我揣著相機(jī)與錄音,去河邊找鬼漓拾。 笑死阁最,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骇两。 我是一名探鬼主播速种,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脯颜!你這毒婦竟也來了哟旗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤栋操,失蹤者是張志新(化名)和其女友劉穎闸餐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矾芙,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舍沙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剔宪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拂铡。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖葱绒,靈堂內(nèi)的尸體忽然破棺而出感帅,到底是詐尸還是另有隱情,我是刑警寧澤地淀,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布失球,位于F島的核電站,受9級特大地震影響帮毁,放射性物質(zhì)發(fā)生泄漏实苞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一烈疚、第九天 我趴在偏房一處隱蔽的房頂上張望黔牵。 院中可真熱鬧,春花似錦爷肝、人聲如沸猾浦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跃巡。三九已至危号,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間素邪,已是汗流浹背外莲。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兔朦,地道東北人偷线。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像沽甥,于是被迫代替她去往敵國和親声邦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

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