響應者鏈及相關機制總結

王小樹發表於2016-06-29
概念

響應者 : 對使用者互動動作事件進行響應的物件。
響應者鏈:成為處理事件的響應者的先後順序鏈。

正文

1、Hit-Test 機制

當使用者觸控(Touch)螢幕進行互動時,系統首先要找到響應者(Responder)。系統檢測到手指觸控(Touch)操作時,將Touch 以UIEvent的方式加入UIApplication事件佇列中。UIApplication從事件佇列中取出最新的觸控事件進行分發傳遞到UIWindow進行處理。UIWindow 會通過hitTest:withEvent:方法尋找觸碰點所在的檢視,這個過程稱之為hit-test view。

hitTest 的順序如下

在頂級檢視(Root View)上呼叫pointInside:withEvent:方法判斷觸控點是否在當前檢視內;
如果返回NO,那麼hitTest:withEvent:返回nil;
如果返回YES,那麼它會向當前檢視的所有子檢視傳送hitTest:withEvent:訊息,所有子檢視的遍歷順序是從最頂層檢視一直到到最底層檢視,即從subviews陣列的末尾向前遍歷,直到有子檢視返回非空物件或者全部子檢視遍歷完畢。
如果有subview的hitTest:withEvent:返回非空物件則A返回此物件,處理結束(注意這個過程,子檢視也是根據pointInside:withEvent:的返回值來確定是返回空還是當前子檢視物件的。並且這個過程中如果子檢視的hidden=YES、userInteractionEnabled=NO或者alpha小於0.1都會並忽略);
如果所有subview遍歷結束仍然沒有返回非空物件,則hitTest:withEvent:返回self;

系統就是這樣通過hit test找到觸碰到的檢視(Initial View)進行響應。

2、響應者鏈 (Responder Chain)

有些時候,Touch後系統通過hit test 機制找到了觸碰到的Initial View,但是Initial view並沒有或者無法正常處理此次Touch。這個時候,系統便會通過響應者鏈尋找下一個響應者,以對此次Touc 進行響應。

響應者鏈順序如下:

                                                  響應者鏈及相關機制總結

示意圖

如果一個View有一個檢視控制器(View Controller),它的下一個響應者是這個檢視控制器,緊接著才是它的父檢視(Super View),如果一直到Root View都沒有處理這個事件,事件會傳遞到UIWindow(iOS中有一個單例Window),此時Window如果也沒有處理事件,便進入UIApplication,UIApplication是一個響應者鏈的終點,它的下一個響應者指向nil,以結束整個迴圈。

3實際開發中常見的相關問題

在實際開發中,經常會遇到檢視沒有響應的情況,特別是新手會經常搞不清楚狀況。
一下是檢視沒有響應的幾個情況:

1.userInteractionEnabled=NO;
2.hidden=YES;
3.alpha=0~0.01;
4.沒有實現touchesBegan:withEvent:方法,直接執行touchesMove:withEvent:等方法;
5.目標檢視點選區域不在父檢視的Frame上 (superView背景色為clear Color的時候經常會忽略這個問題)。

在某些情景下,我們在點選子檢視的時候仍然需要呼叫父檢視的touchesBegan:withEvent:等方法,例如我們在父檢視上新增了一個覆蓋範圍了父檢視大部分面積的TableView或ScrollerView 或其他View,而我們要通過父檢視的touchesBegan:withEvent:方法來收鍵盤。
這個時候我們可以通過UIView的類別,重寫touch相關方法,程式碼如下:

我在我的github:WXSTools 放了個平時寫來自己用的部分工具類的集合,裡面的UIView+Touch可以作為Demo程式碼。
首發連結:http://www.jianshu.com/p/31e9b9e16411

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

響應者鏈及相關機制總結 響應者鏈及相關機制總結

相關文章