iOS隨筆——UIResponder與UIGestureRecognizer

觸屏事件(Touch Event)


UIResponder

閱讀前請先了解一下以下2個方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

首先通過一個例子來了解一下UIResponder事件分發(fā)和響應(yīng)者鏈的過程(用戶點擊視圖View E)。

example.png
1.事件分發(fā)

(1)iOS系統(tǒng)檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象募闲,并放入當(dāng)前活動Application的事件隊列舶吗,單例的UIApplication會從事件隊列中取出觸摸事件并傳遞給單例的UIWindow來處理

(2)A是UIWindow的根視圖妻导,因此尤蒿,UIWindwo對象會首相對A進行hit-test假消,顯然用戶點擊的范圍是在A的范圍內(nèi)捷犹,因此红选,pointInside:withEvent:返回了YES澜公,這時會繼續(xù)檢查A的子視圖

(3)子視圖B點擊的范圍不再B內(nèi),因此B分支的pointInside:withEvent:返回NO喇肋,對應(yīng)的hitTest:withEvent:返回nil坟乾;子視圖C點擊的范圍在C內(nèi),即C的pointInside:withEvent:返回YES

(4)子視圖D點擊的范圍不再D內(nèi)蝶防,因此D的pointInside:withEvent:返回NO甚侣,對應(yīng)的hitTest:withEvent:返回nil;子視圖E點擊的范圍在E內(nèi)间学,即E的pointInside:withEvent:返回YES殷费,由于E沒有子視圖(也可以理解成對E的子視圖進行hit-test時返回了nil),因此低葫,E的hitTest:withEvent:會將E返回详羡,再往回回溯,就是C的hitTest:withEvent:返回E--->>A的hitTest:withEvent:返回E嘿悬。

至此实柠,本次點擊事件的第一響應(yīng)者就通過響應(yīng)者鏈的事件分發(fā)邏輯成功的找到了。

補充說明
hitTest:withEvent:方法將會忽略隱藏(hidden=YES)的視圖鹊漠,禁止用戶操作(userInteractionEnabled=YES)的視圖主到,以及alpha級別小于0.01(alpha<0.01)的視圖。如果一個子視圖的區(qū)域超過父視圖的bound區(qū)域(父視圖的clipsToBounds 屬性為NO躯概,這樣超過父視圖bound區(qū)域的子視圖內(nèi)容也會顯示)登钥,那么正常情況下對子視圖在父視圖之外區(qū)域的觸摸操作不會被識別,因為父視圖的pointInside:withEvent:方法會返回NO,這樣就不會繼續(xù)向下遍歷子視圖了。當(dāng)然娶靡,也可以重寫pointInside:withEvent:方法來處理這種情況牧牢。

2.響應(yīng)者鏈
UIResponder.jpeg

當(dāng)發(fā)生事件響應(yīng)時,必須知道由誰來響應(yīng)事件姿锭。在 iOS 中塔鳍,由響應(yīng)者鏈來對事件進行響應(yīng)。

(1)所有事件響應(yīng)的類都是 UIResponder 的子類呻此,響應(yīng)者鏈?zhǔn)且粋€由不同對象組成的層次結(jié)構(gòu)轮纫,其中的每個對象將依次獲得響應(yīng)事件消息的機會。當(dāng)發(fā)生事件時焚鲜,事件首先被發(fā)送給第一響應(yīng)者掌唾,第一響應(yīng)者則是通過響應(yīng)者鏈的事件分發(fā)邏輯來確定的放前。

(2)如果第一響應(yīng)者無法響應(yīng)事件或者hit-test沒有找到第一響應(yīng)者,事件會隨著響應(yīng)鏈向上回溯糯彬,回溯順序如圖凭语,如果UIWindow實例和UIApplication實例都不能處理該事件,則該事件會被丟棄

(3)一般來說撩扒,第一響應(yīng)者是個視圖對象或者其子類對象似扔,當(dāng)其被觸摸后事件被交由它處理,如果它不處理搓谆,事件就會被傳遞給它的視圖控制器對象 ViewController(如果存在)炒辉,然后是它的父視圖(superview)對象(如果存在),以此類推泉手,直到頂層視圖辆脸。接下來會沿著頂層視圖(top view)到窗口(UIWindow 對象)再到程序(UIApplication 對象)。如果整個過程都沒有響應(yīng)這個事件螃诅,該事件就被丟棄。一般情況下状囱,在響應(yīng)者鏈中只要由對象處理事件术裸,事件就停止傳遞。

UIGestureRecognizer


假設(shè)如果沒有手勢亭枷,如果我們需要監(jiān)聽視圖的手勢則需要通過這四個方法

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event;

通過這些方法監(jiān)聽用戶手勢行為有明顯的缺點
(1)需要自定義視圖
(2)默認情況袭艺,外界不知道監(jiān)聽的觸摸事件情況
(3)不容易規(guī)范的區(qū)分具體手勢行為
因此蘋果推出了一系列的手勢行為,來簡化開發(fā)難度

現(xiàn)在來討論一下叨粘,UIGestureRecognizer和UIResponder的優(yōu)先級
如果在視圖A上添加一個Tap手勢猾编,此時點擊視圖E,則會發(fā)現(xiàn)并沒有響應(yīng)視圖E的action而是執(zhí)行了視圖A上Tap手勢的action

UITouch.png

我們會發(fā)現(xiàn)手勢(2)的優(yōu)先級比所綁定的視圖(3)的優(yōu)先級高

到這里我們不妨再推敲一下,為什么要這樣設(shè)計這個機制呢?不能等view判斷自己能否處理之后再往下傳遞么?
答:如果是父view是縮放手勢,如果按照依次傳遞會怎么樣?可以看出在處理的時效性可準(zhǔn)確性方面不如這么設(shè)計好.
那蘋果的文檔在hit-test說的就是最上面的view處理不了再交給后面的view啊?這不矛盾么?
答:這不矛盾,我們看文檔不能斷章取義,不能太機械,蘋果在hit-test中說的是一種宏觀上的表現(xiàn)形式.
hit-test的目標(biāo)就是抓住touch對應(yīng)的響應(yīng)者鏈的頭,這樣我們就可以分發(fā)了,不然我們?nèi)绾胃咝シ职l(fā)呢?

參考資料
https://hit-alibaba.github.io/interview/iOS/Cocoa-Touch/Event-Handling.html
http://blog.csdn.net/zhoupengju/article/details/52250135

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末升敲,一起剝皮案震驚了整個濱河市答倡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驴党,老刑警劉巖瘪撇,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異港庄,居然都是意外死亡倔既,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門鹏氧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渤涌,“玉大人,你說我怎么就攤上這事把还∈蹬睿” “怎么了茸俭?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞳秽。 經(jīng)常有香客問我瓣履,道長,這世上最難降的妖魔是什么练俐? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任袖迎,我火速辦了婚禮,結(jié)果婚禮上腺晾,老公的妹妹穿的比我還像新娘燕锥。我一直安慰自己,他們只是感情好悯蝉,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布归形。 她就那樣靜靜地躺著,像睡著了一般鼻由。 火紅的嫁衣襯著肌膚如雪暇榴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天蕉世,我揣著相機與錄音蔼紧,去河邊找鬼。 笑死狠轻,一個胖子當(dāng)著我的面吹牛奸例,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播向楼,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼查吊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了湖蜕?” 一聲冷哼從身側(cè)響起逻卖,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎重荠,沒想到半個月后箭阶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡戈鲁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年仇参,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婆殿。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡诈乒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婆芦,到底是詐尸還是另有隱情怕磨,我是刑警寧澤喂饥,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肠鲫,受9級特大地震影響员帮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜导饲,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一捞高、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渣锦,春花似錦硝岗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至听盖,卻和暖如春胀溺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背皆看。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工月幌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悬蔽。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像捉兴,于是被迫代替她去往敵國和親蝎困。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

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

  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件倍啥。本想自己總結(jié)一下禾乘,但是遇到了這篇文章,感覺總結(jié)的已經(jīng)很到位虽缕,特此轉(zhuǎn)載始藕。作者:L...
    WQ_UESTC閱讀 6,010評論 4 26
  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點擊了氮趋?糾結(jié)于如何實現(xiàn)這個奇葩響應(yīng)需求伍派?亦或是...
    Lotheve閱讀 57,082評論 51 599
  • 用戶以多種方式操縱他們的iOS設(shè)備,例如觸摸屏幕或搖動設(shè)備剩胁。 iOS會解釋用戶何時以及如何操作硬件并將此信息傳遞到...
    坤坤同學(xué)閱讀 3,994評論 7 19
  • 在IOS開發(fā)中會遇到各種操作事件诉植,通過程序可以對這些事件做出響應(yīng)。 首先昵观,當(dāng)發(fā)生事件響應(yīng)時晾腔,必須知道由誰來響應(yīng)事件...
    烏七貓閱讀 354評論 0 0
  • 什么是事件? iOS中事件分為3大類 : 觸摸事件, 加速計事件和遠程控制事件.當(dāng)你的手指在手機屏幕上觸摸時, 產(chǎn)...
    iYeso閱讀 171評論 0 1