什么是事件響應(yīng)鏈
對于ios設(shè)備的用戶來說,我們操作手機(jī)的方式有三種:觸摸屏幕、晃動設(shè)備、通過遙控設(shè)施控制設(shè)備。
對應(yīng)的有下面三響應(yīng)時間類型:
- 觸屏事件(Touch Event)
- 運(yùn)動事件 (Motion Event)
- 遠(yuǎn)端控制事件 (Remote-control Event)
響應(yīng)者鏈條
- 響應(yīng)者對象:能夠響應(yīng)和處理響應(yīng)事件能力的對象。響應(yīng)者鏈條就是有響應(yīng)者對組成的層次結(jié)構(gòu)。
- UIResponder類 能夠響應(yīng)和處理響應(yīng)事件的基類,所有能夠響應(yīng)和處理響應(yīng)事件的類都直接或間接繼承與該類。我們熟悉的UIApplication、 UIViewController、UIWindow和所有繼承自UIView的UIKit類都直接或間接的繼承自UIResponder,所以它們的實例都是可以構(gòu)成響應(yīng)者鏈的響應(yīng)者對象。
響應(yīng)者鏈條有以下特點:
- 響應(yīng)者鏈通常是由視圖(UIView)構(gòu)成的;
- 一個視圖的下一個響應(yīng)者是它視圖控制器(UIViewController)(如果有的話),然后再轉(zhuǎn)給它的父視圖(Super View);
- 視圖控制器(如果有的話)的下一個響應(yīng)者為其管理的視圖的父視圖;
- 單例的窗口(UIWindow)的內(nèi)容視圖將指向窗口本身作為它的下一個響應(yīng)者需要指出的是,Cocoa Touch應(yīng)用不像Cocoa應(yīng)用,它只有一個UIWindow對象,因此整個響應(yīng)者鏈要簡單一點;
- 單例的應(yīng)用(UIApplication)是一個響應(yīng)者鏈的終點,它的下一個響應(yīng)者指向nil,以結(jié)束整個循環(huán)。
點擊屏幕時是如何互動的
- iOS系統(tǒng)檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象,并放入當(dāng)前活動Application的事件隊列,單例的UIApplication會從事件隊列中取出觸摸事件并傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點所在的視圖(View),即需要將觸摸事件傳遞給其處理的視圖,這個過程稱之為hit-test view。
- UIWindow實例對象會首先在它的內(nèi)容視圖上調(diào)用hitTest:withEvent:,此方法會在其視圖層級結(jié)構(gòu)中的每個視圖上調(diào)用pointInside:withEvent:(該方法用來判斷點擊事件發(fā)生的位置是否處于當(dāng)前視圖范圍內(nèi),以確定用戶是不是點擊了當(dāng)前視圖),如果pointInside:withEvent:返回YES,則繼續(xù)逐級調(diào)用,直到找到touch操作發(fā)生的位置,這個視圖也就是要找的hit-test view。
- hitTest:withEvent:方法的處理流程如下:首先調(diào)用當(dāng)前視圖的pointInside:withEvent:方法判斷觸摸點是否在當(dāng)前視圖內(nèi);若返回NO,則hitTest:withEvent:返回nil;若返回YES,則向當(dāng)前視圖的所有子視圖(subviews)發(fā)送hitTest:withEvent:消息,所有子視圖的遍歷順序是從最頂層視圖一直到到最底層視圖,即從subviews數(shù)組的末尾向前遍歷,直到有子視圖返回非空對象或者全部子視圖遍歷完畢;若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象,處理結(jié)束;如所有子視圖都返回非,則hitTest:withEvent:方法返回自身(self)。
事件的傳遞和響應(yīng)分兩個鏈:
- 傳遞鏈:由系統(tǒng)向離用戶最近的view傳遞。UIKit –> active app’s event queue –> window –> root view –>……–>lowest view
- 響應(yīng)鏈:由離用戶最近的view向系統(tǒng)傳遞。initial view –> super view –> …..–> view controller –> window –> Application