The Responder Chain(響應者鏈)
一、響應者物件
Responder Object,即響應者物件,是指有響應和處理事件的能力的物件。所有的響應者都繼承了 UIResponder (iOS) 或者 NSResponder (OS X),這些響應者類聲明瞭事件處理的程式識別介面,並且定義了預設的響應行為。程式裡面的可視物件大部分都是響應者,例如windows,views和controls。app 物件當然也是響應者,在iOS系統中,檢視控制器物件(UIViewController object)也是響應者物件。
左側描述iOS平臺,右側描述OS X平臺
為了接收事件,響應者類(responder)必須實現對應的事件處理方法,並且在某些情況下告訴程式它(responder)可以作為第一響應者(the first responder)
- 第一響應者
The First Responder,在程式中,那些首先接收多種事件的響應者物件叫做第一響應者。它可以接收按鍵事件(key events),移動事件(motion events)和動作訊息(action messages)。第一響應者通常是程式中最適合處理事件的window中的檢視。為了接收事件,響應者必須指明它將自發成為第一響應者。
// OS X 平臺
- (BOOL)acceptsFirstResponder { return YES; }
//iOS 平臺
- (BOOL)canBecomeFirstResponder { return YES; }
注意:滑鼠事件和多點觸控事件首先傳遞到點選的檢視,它可能是第一響應者,也可能不是。也就是說touch 事件處理並不關心響應物件是不是第一響應者,它只看物件是不是在點選區域內。比如一個View設定為FirstResponder,但是點選它裡面的按鈕還是會響應按鈕的方法。
第一響應者物件做隱藏操作不會改變它作為第一響應者的狀態,必須手動resign才會改變。
二、響應者鏈
The Responder Chain,即響應者鏈,是由一系列的響應者物件(Responder Object)組成的一個事件傳遞(Event Delivery)序列。
響應者鏈架構圖:左側ios,右側OS X
當事件發生時,首先從第一響應者或者點選區域的View開始響應,如果當前響應者不能響應事件,則向上傳遞到響應鏈中的下一個響應者(nextResponder),如果事件一直沒有消耗掉(響應處理),則一直傳遞到 window 物件,然後傳遞到全域性app物件,還不能消耗掉,則系統會廢棄這個事件。
三、Hit-Testing
在iOS平臺上通過hit-testing 來識別響應touch的View。
每當我們在應用程式中觸碰螢幕時,UIKit 生成一個 UIEvent 物件,並且將這個物件傳遞給當前active application ,之後單例UIApplication就會從它的事件佇列裡面取出一個事件進行響應。
UIApplication 就是通過hit-testing 來識別響應事件的view。首先UIApplication將接收到的UIEvent物件傳遞給UIWindow,UIWindow在傳遞給其subviews,依次向下傳遞,直到找到響應事件的最底層的view。
hit-testing首先檢查touch是不是在view的區域內,如果不在區域內則不向下檢查,返回自身,然後按照新增順序的逆序遍歷其他兄弟檢視,直到找到響應事件view
如下圖:
檢視新增順序 :
xxView add A;
A add B;
A add C;
C add D;
C add E;
1、hit-testing首先檢查touch是否在A區域中,如果在則檢查其子檢視C
2、hit-teting檢查touch是否在C區域中,如果在,檢查其子檢視,如果不在則檢查兄弟檢視B;
3、如果檢查A的子檢視B也不能響應事件,返回檢視A,開始檢查A的兄弟檢視。