Event Delivery: The Responder Chain理論與實(shí)踐

關(guān)于事件傳遞響應(yīng)者鏈的定義和使用,建議直接詳細(xì)閱讀蘋果官方文檔(避免不恰當(dāng)?shù)亩种R(shí)):
https://developer.apple.com/library/content/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html#//apple_ref/doc/uid/TP40009541-CH4-SW2

當(dāng)用戶點(diǎn)擊觸摸時(shí),iOS系統(tǒng)使用hit-testing來(lái)尋找接觸點(diǎn)下面的視圖。hit-testing 檢查接觸點(diǎn)是否在相關(guān)的視圖對(duì)象內(nèi)部,如果在,它會(huì)遞歸檢查該視圖的每個(gè)子視圖,視圖層級(jí)樹(shù)最下面的包含接觸點(diǎn)的視圖會(huì)成為所謂的hit-test視圖。當(dāng)iOS系統(tǒng)獲得了hit-test視圖,系統(tǒng)將觸摸事件傳遞給該視圖由該視圖響應(yīng)。

在這個(gè)過(guò)程中,主要用到以下兩個(gè)方法:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;   // default returns YES if point is in bounds

hitTest:withEvent:會(huì)被視圖對(duì)象的
pointInside:withEvent:方法調(diào)用。如果
hitTest:withEvent:的參數(shù)point在這個(gè)視圖內(nèi)部,說(shuō)明觸摸點(diǎn)在視圖里面,
pointInside:withEvent:方法會(huì)返回YES;然后該視圖的所有子視圖只要pointInside:withEvent:返回YES的,都會(huì)調(diào)用hitTest:withEvent:方法,否則不會(huì)調(diào)用。如果hit-test視圖對(duì)象不能處理點(diǎn)擊事件,點(diǎn)擊事件會(huì)順著響應(yīng)者鏈一直傳播,直到系統(tǒng)找到某個(gè)可以處理它的對(duì)象。

講原理很簡(jiǎn)單,容易懂。但是原理應(yīng)用實(shí)際,就非??疾鞂?shí)用水平了。思考響應(yīng)者鏈可能的應(yīng)用場(chǎng)景,包括但不限于點(diǎn)擊蒙板下面的按鈕,蒙板不響應(yīng)觸摸事件,tableView中的滑動(dòng)控件等等。

在項(xiàng)目中經(jīng)常碰到響應(yīng)者鏈問(wèn)題,終于能將理論與實(shí)踐統(tǒng)一起來(lái)了。

就比如如下場(chǎng)景:

UITableViewCell中有UIDatePickerUIPickerView子視圖用于選取時(shí)間和事件。
會(huì)出現(xiàn)如下問(wèn)題:觸摸Picker view下部往上滑動(dòng)時(shí),Picker view不滑動(dòng),反而是tableView隨著手指滑動(dòng)。只有當(dāng)手指剛好觸摸在Picker view的文字上并且滑動(dòng)時(shí),才會(huì)讓Picker view滑動(dòng)。即Picker view響應(yīng)區(qū)域并非它的frame,而是文字所在區(qū)域,造成用戶難以滑動(dòng)Picker view進(jìn)行選取操作。

期望的效果:只要滑動(dòng)觸摸在Picker view視圖內(nèi)部范圍,都是滑動(dòng)Picker view,而非tableView。

這是一個(gè)響應(yīng)者鏈問(wèn)題,觸摸事件從UIApplication單例一路傳遞,先傳遞到tableView,后傳遞到Picker view。從表現(xiàn)來(lái)看,應(yīng)該是觸摸在Picker view的文字區(qū)域,由Picker view負(fù)責(zé)響應(yīng);觸摸在Picker view的空白區(qū)域,由tableView負(fù)責(zé)響應(yīng)。這會(huì)造成用戶非常難操作。

解決方案:

步驟1.

以下代碼解決的問(wèn)題是觸摸在MMTimeSelectorCell時(shí)MMTimelineMaskView不響應(yīng)事件。即手指在MMTimeSelectorCell上滑動(dòng)時(shí),不讓tableView滑動(dòng)。

圖1
步驟2.

MMTimeSlectorCell中終止響應(yīng)鏈,如下圖。
因?yàn)槿绻械淖右晥D都沒(méi)有響應(yīng)的話,在父視圖的hitTest:withEvent方法中會(huì)返回自身,想要響應(yīng)事件的子視圖將無(wú)法獲取事件。

圖2

這樣就能讓用戶正?;瑒?dòng)Picker view了,只要滑動(dòng)觸摸點(diǎn)在Picker view范圍以內(nèi),都可以滑動(dòng)Picker view,而不是tableView。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS開(kāi)發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺(jué)總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,236評(píng)論 4 26
  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點(diǎn)擊了?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求?亦或是...
    Lotheve閱讀 59,429評(píng)論 51 604
  • 用戶以多種方式操縱他們的iOS設(shè)備,例如觸摸屏幕或搖動(dòng)設(shè)備。 iOS會(huì)解釋用戶何時(shí)以及如何操作硬件并將此信息傳遞到...
    坤坤同學(xué)閱讀 4,116評(píng)論 7 19
  • 7、不使用IB是,下面這樣做有什么問(wèn)題? 6、請(qǐng)說(shuō)說(shuō)Layer和View的關(guān)系,以及你是如何使用它們的。 1.首先...
    AlanGe閱讀 987評(píng)論 0 1
  • 本文來(lái)自:http://ios.jobbole.com/84081/ 前言: 按照時(shí)間順序,事件的生命周期是這樣的...
    HackerOnce閱讀 2,940評(píng)論 1 10

友情鏈接更多精彩內(nèi)容