iOS事件傳遞和響應(yīng)機制

一部iOS設(shè)備會產(chǎn)生各種各樣的事件(UIEvent 實例)比如:觸摸屏幕、遠程控制等芽偏,這些事件發(fā)生了就需要有響應(yīng)者(UIResponder 實例)去響應(yīng)這些事件雷逆。這就需要一套事件響應(yīng)機制。

事件類型

查看UIEventType的定義,我們知道有4種事件類型哮针。

typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches,
    UIEventTypeMotion,
    UIEventTypeRemoteControl,
    UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),
};

其中UIEventTypeTouches就是觸摸手機屏幕產(chǎn)生的事件关面。UIEventTypeMotion我們能接觸到的就可能是手機的shake,也就是搖晃事件了十厢。UIEventTypeRemoteControl等太,UIEventTypePresses對于手機App開發(fā)者一般遇不到。UIEventTypePresses的名字有一定的迷惑性蛮放,其實它指的是物理按鍵被按下缩抡,比如電視的遙控器。

除了UIEventTypeTouches其他事件我們都難以遇到包颁。

事件響應(yīng)者和響應(yīng)鏈

能響應(yīng)事件的都是UIResponder及其子類瞻想。常見的UIResponder的子類有:UIViewUIViewController娩嚼,UIApplicationUIApplicationDelegate

下面這張圖是Apple官方文檔中的圖蘑险,可以看出事件的響應(yīng)鏈與視圖的層級關(guān)系基本一致。值得注意的是響應(yīng)鏈的末端是...->UIWindow->UIApplication->UIApplicationDelegate岳悟。一個UIRespondernextResponder指向它的下一個響應(yīng)者佃迄。你可以重寫(override)nextResponder方法改變下一個響應(yīng)者。實際上有些類已經(jīng)重寫了nextResponder贵少,比如一個UIView如果是UIController的根視圖呵俏,它的nextResponder會指向view controller。詳見 Using Responders and the Responder Chain to Handle Events
Altering the Responder Chain一節(jié)滔灶。

事件響應(yīng)鏈

如果順著響應(yīng)鏈沒有發(fā)現(xiàn)能夠響應(yīng)事件的響應(yīng)者普碎,那么這個事件就會被忽略

我們看到录平,UIResponder中對應(yīng)每種事件類型都有對應(yīng)的事件響應(yīng)方法麻车,比如對于touch事件來說有touchesBegan: withEvent:,touchesMoved: withEvent:,touchesCancelled: withEvent:,touchesEnded: withEvent:,還有對于motion事件來說有motionBegan: withEvent:,motionEnded: withEvent:,motionCancelled: withEvent:缀皱。還有針對其他事件的方法,你可以去UIResponder類里去查看动猬。

如果一個UIResponder子類重寫(override)了上述所說事件響應(yīng)方法唆鸡,那么事件就算這個被這個類的實例響應(yīng)了。事件就不再會沿著響應(yīng)鏈傳遞枣察。一個UIControl(UIButton是UIControl的子類),不管它有沒有被增加一個target燃逻,事件傳遞到它這里就終止了序目。我猜UIControl內(nèi)部實現(xiàn)了上面說的幾個響應(yīng)事件的方法。

比如一個UIView子類重寫了touchesBegan: withEvent:,touchesMoved: withEvent:,touchesCancelled: withEvent:,touchesEnded: withEvent:伯襟,如果有觸摸事件傳遞到這個子類的實例猿涨,就會調(diào)用這些方法,并停止向下傳遞姆怪。

事件傳遞機制

上面說的事件響應(yīng)鏈有一個起點叛赚,這個起點叫做first responder。每一種事件都有找到或者指定first responder的規(guī)則稽揭,這里我們只關(guān)心觸摸事件(touch event)俺附。

當手機屏幕被觸摸,系統(tǒng)將其包裝成觸摸事件(touch event)并傳遞給UIApplication,UIApplication傳遞給UIWindow(也是一個UIView的子類)溪掀,UIWindow調(diào)用hitTest:withEvent:淋昭,得到一個能夠響應(yīng)觸摸事件(touch event)的UIView缚忧。

UIViewhitTest:withEvent:方法,會遍歷view的層級結(jié)構(gòu),找到能夠響應(yīng)這個事件的最深層的子視圖痕鳍,成為觸摸事件的first responder。如果first responder不能響應(yīng)事件冰垄,這個事件就會沿事件響應(yīng)鏈傳遞直到被響應(yīng)或者被忽略滑绒。

htiTest

上面的圖片展示了hitTest:withEvent:是如何實現(xiàn)的。其中幾個點我們需要注意骚勘,首先判斷的是hidden,userInteractionEnable和alpha這幾個屬性铐伴,然后使用pointInside:withEvent:判斷點擊事件是否發(fā)生在該UIView內(nèi)。然后是倒序遍歷所有子視圖并調(diào)用他們的hitTest:withEvent:方法调鲸。

事件傳遞機制原理的幾個應(yīng)用

1盛杰、非矩形可點擊區(qū)域。比如一個button的一個圓形區(qū)域可以被點擊藐石,其他區(qū)域不可點擊即供。只要重寫pointInside:withEvent:,在圓形區(qū)域的點返回YES于微,不在圓形區(qū)域的返回NO逗嫡。

2青自、按鈕超出父視圖。默認情況下驱证,按鈕超出父視圖的部分是不可以點擊的延窜。我們可以重寫父視圖的pointInside:withEvent:方法,讓按鈕超出父視圖的部分也返回YES抹锄。

參考:

1. Using Responders and the Responder Chain to Handle Events

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逆瑞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子伙单,更是在濱河造成了極大的恐慌获高,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吻育,死亡現(xiàn)場離奇詭異念秧,居然都是意外死亡,警方通過查閱死者的電腦和手機布疼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門摊趾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人游两,你說我怎么就攤上這事砾层。” “怎么了器罐?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵梢为,是天一觀的道長。 經(jīng)常有香客問我轰坊,道長铸董,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任肴沫,我火速辦了婚禮粟害,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘颤芬。我一直安慰自己悲幅,他們只是感情好,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布站蝠。 她就那樣靜靜地躺著汰具,像睡著了一般。 火紅的嫁衣襯著肌膚如雪菱魔。 梳的紋絲不亂的頭發(fā)上留荔,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機與錄音澜倦,去河邊找鬼聚蝶。 笑死杰妓,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的碘勉。 我是一名探鬼主播巷挥,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼验靡!你這毒婦竟也來了倍宾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤胜嗓,失蹤者是張志新(化名)和其女友劉穎凿宾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兼蕊,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年件蚕,在試婚紗的時候發(fā)現(xiàn)自己被綠了孙技。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡排作,死狀恐怖牵啦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妄痪,我是刑警寧澤哈雏,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站衫生,受9級特大地震影響裳瘪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罪针,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一彭羹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泪酱,春花似錦派殷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至斯撮,卻和暖如春经伙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吮成。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工橱乱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辜梳,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓泳叠,卻偏偏與公主長得像作瞄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子危纫,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354