響應鏈相關知識點

術語

? ? ? ?hit-testing ? ? ? ? ?點擊檢測

? ? ? ?responder chain ? 響應鏈


響應鏈可以做到的事情

通過相應鏈榴嗅,我們可以改變用戶操作的響應順序

可以查找到視圖的響應控制器



事件流程

當用戶觸發(fā)的一個事件發(fā)生靶瘸,UIKit會創(chuàng)建一個包含要處理的事件信息的事件對象。然后她會將事件對象放入active app’s(應用程序對象江咳,每個程序對應唯一一個)事件隊列(為什么是隊列而不是棧叮喳?因為隊列是先進先出睁宰,用于保證先產生的事件先處理,棧是先進后出)嘱么。對于觸摸事件狮含,事件對象就是UIEvent對象封裝的一系列觸摸集合。對于動作事件拱撵,這個事件對象依賴于使用的framework和你關心哪種動作事件辉川。

事件通過特殊的路徑傳遞直到被傳遞到一個可以處理該事件的對象。首先拴测,單例的UIApplication對象從頂層的隊列中獲取事件乓旗,然后分發(fā)。典型的集索,它將事件發(fā)送到App的關鍵window(key window)對象屿愚,window則為了處理該事件而發(fā)送它到初始化對象(initial object),這個初始化對像依靠事件類型务荆。

初始化對象查找后的反饋過程如下圖

For the app on the left, the event follows this path:

The initial view attempts to handle the event or message. If it can’t handle the event, it passes the event to its superview, because the initial view is not the top most view in its view controller’s view hierarchy.

The superview attempts to handle the event. If the superview can’t handle the event, it passes the event to its superview, because it is still not the top most view in the view hierarchy.

The topmost view in the view controller’s view hierarchy attempts to handle the event. If the topmost view can’t handle the event, it passes the event to its view controller.

The view controller attempts to handle the event, and if it can’t, passes the event to the window.

If the window object can’t handle the event, it passes the event to the singleton app object.

If the app object can’t handle the event, it discards the event.

The app on the right follows a slightly different path, but all event delivery paths follow these heuristics:

A view passes an event up its view controller’s view hierarchy until it reaches the topmost view.

The topmost view passes the event to its view controller.

The view controller passes the event to its topmost view’s superview.

Steps 1-3 repeat until the event reaches the root view controller.

The root view controller passes the event to the window object.

The window passes the event to the app object.

左邊的情況妆距,最初的視圖接收到事件,如果它不能處理函匕,那么它將會傳遞給它的父試圖娱据,它的父試圖也不能處理,再傳遞給父試圖的父試圖盅惜,如果還不能處理中剩,再傳遞給ViewController,也不能處理抒寂,傳遞給window结啼,也不能處理,傳遞給Application屈芜。

右邊的情況郊愧,最初的視圖它不能處理時會將事件傳遞給它的視圖控制器朴译,視圖控制器會將事件會將事件傳遞給視圖控制器的視圖的父試圖,然后重復這樣的過程属铁,直到根視圖控制器眠寿,也不能處理,傳遞給window红选,也不能處理澜公,傳遞給Application

蘋果說兩種app設置的原因,但是基本都是如果初始化對象(initial object)—— 即hit-test view或者first responder —— 不處理事件喇肋,UIKit會將事件傳遞給responder chain的下一個responder坟乾。每個responder決定它是傳遞事件還是通過nextResponder方法傳遞給它的下一個responder。這個操作繼續(xù)直到一個responder處理event或者沒有responder了蝶防。

總而言之:

事件的傳遞和響應分兩個鏈:

傳遞鏈:由系統(tǒng)向離用戶最近的view傳遞甚侣。UIKit –> active app’s event queue –> window –> root view –>……–>lowest view

響應鏈:由離用戶最近的view向系統(tǒng)傳遞。initial view –> super view –> …..–> view controller –> window –> Application(如果view是控制器的view间学,就傳遞給控制器殷费;如不是,則將其傳遞給它的父視圖 在視圖層次結構的最頂級視圖低葫,如果也不能處理收到的事件或消息详羡,則其將事件或消息傳遞給window對象進行處理 如果window對象也不處理,則其將事件或消息傳遞給UIApplication對象 如果UIApplication也不能處理該事件或消息嘿悬,則將其丟棄)

上面是原理实柠,下面說方法:

- (UIView * _Nullable)hitTest:(CGPoint)point withEvent:(UIEvent * _Nullable)event

此方法會在視圖層級結構中的每個視圖上調用

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent * _Nullable)event

如果pointInside:withEvent:返回YES,則繼續(xù)逐級調用,直到找到touch操作發(fā)生的位置善涨,這個視圖也就是hit-test view窒盐。

hitTest:withEvent:方法的處理流程如下:

首先調用當前視圖的pointInside:withEvent:方法判斷觸摸點是否在當前視圖內;

若返回NO,則hitTest:withEvent:返回nil;

若返回YES,則向當前視圖的所有子視圖(subviews)發(fā)送hitTest:withEvent:消息钢拧,所有子視圖的遍歷順序是從top到bottom蟹漓,即從subviews數(shù)組的末尾向前遍歷,直到有子視圖返回非空對象或者全部子視圖遍歷完畢;

若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象源内,處理結束葡粒;

如所有子視圖都返回非,則hitTest:withEvent:方法返回自身(self)膜钓。

hitTest:withEvent:忽略的三種情況:

1:hidden = YES 的視圖

2:userInteractionEnabled = YES 的視圖

3:alpha < 0.01 的視圖

如果一個子視圖的區(qū)域超過父視圖的bound區(qū)域(父視圖的clipsToBounds 屬性為NO,這樣超過父視圖bound區(qū)域的子視圖內容也會顯示)塔鳍,那么正常情況下對子視圖在父視圖之外區(qū)域的觸摸操作不會被識別,因為父視圖的pointInside:withEvent:方法會返回NO,這樣就不會繼續(xù)向下遍歷子視圖了。當然呻此,也可以重寫pointInside:withEvent:方法來處理這種情況。(objc_setAssociatedObject添加屬性腔寡,擴展響應區(qū)域)

如果父視圖需要對對哪個子視圖可以響應觸摸事件做特殊控制焚鲜,則可以重寫hitTest:withEvent:或pointInside:withEvent:方法。

如button,scrollview同為topView的子視圖,但scrollview覆蓋在button之上忿磅,這樣在在button上的觸摸操作返回的hit-test view為scrollview,button無法響應糯彬,可以修改topView的hitTest:withEvent:方法如下:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

? ? ? UIView *result = [super hitTest:point withEvent:event];

? ? ? CGPoint buttonPoint = [underButton convertPoint:point fromView:self];

? ? ? if ([underButton pointInside:buttonPoint withEvent:event]) {

? ? ? ? ? return underButton;

? ? ? ?}

? ? ? return result;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市葱她,隨后出現(xiàn)的幾起案子撩扒,更是在濱河造成了極大的恐慌,老刑警劉巖吨些,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搓谆,死亡現(xiàn)場離奇詭異,居然都是意外死亡豪墅,警方通過查閱死者的電腦和手機泉手,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偶器,“玉大人斩萌,你說我怎么就攤上這事∑梁洌” “怎么了钝鸽?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵道川,是天一觀的道長。 經(jīng)常有香客問我,道長匠璧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任晤揣,我火速辦了婚禮旗芬,結果婚禮上,老公的妹妹穿的比我還像新娘升敲。我一直安慰自己答倡,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布驴党。 她就那樣靜靜地躺著瘪撇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪港庄。 梳的紋絲不亂的頭發(fā)上倔既,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音鹏氧,去河邊找鬼渤涌。 笑死,一個胖子當著我的面吹牛把还,可吹牛的內容都是我干的实蓬。 我是一名探鬼主播茸俭,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼安皱!你這毒婦竟也來了调鬓?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤酌伊,失蹤者是張志新(化名)和其女友劉穎腾窝,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體居砖,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡虹脯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悯蝉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片归形。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鼻由,靈堂內的尸體忽然破棺而出暇榴,到底是詐尸還是另有隱情,我是刑警寧澤蕉世,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布蔼紧,位于F島的核電站,受9級特大地震影響狠轻,放射性物質發(fā)生泄漏奸例。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一向楼、第九天 我趴在偏房一處隱蔽的房頂上張望查吊。 院中可真熱鬧,春花似錦湖蜕、人聲如沸逻卖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽评也。三九已至,卻和暖如春灭返,著一層夾襖步出監(jiān)牢的瞬間盗迟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工熙含, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罚缕,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓怎静,卻偏偏與公主長得像怕磨,于是被迫代替她去往敵國和親喂饥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內容

  • 重點參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,410評論 0 15
  • 前言 按照時間順序肠鲫,事件的生命周期是這樣的: 事件的產生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vie...
    歡博閱讀 585評論 0 3
  • 前言: 按照時間順序,事件的生命周期是這樣的: 事件的產生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vi...
    reviewThis閱讀 722評論 1 2
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件或粮。本想自己總結一下导饲,但是遇到了這篇文章,感覺總結的已經(jīng)很到位氯材,特此轉載渣锦。作者:L...
    WQ_UESTC閱讀 5,996評論 4 26
  • 如果你對18歲的自己說一句話,你會說什么氢哮? 我其實突然理解了我媽袋毙,因為現(xiàn)在的我想對當時的自己說的,都是她當時告訴我...
    爆炸寶閱讀 179評論 0 0