事件的傳遞和響應(yīng)者鏈

事件的產(chǎn)生和傳遞過程:

1.發(fā)生觸摸事件后,系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的隊(duì)列事件中

2.UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,并將事件分發(fā)下去以便處理,通常會(huì)先發(fā)送事件給應(yīng)用程序的主窗口(keyWindow)

3.主窗口會(huì)在視圖層次結(jié)構(gòu)中找到一個(gè)最合適的視圖來處理觸摸事件

4.找到合適的視圖控件后,就會(huì)調(diào)用視圖控件的touches方法來作事件的具體處理:touchesBegin… touchesMoved…touchesEnded等

5.這些touches方法默認(rèn)的做法是將事件順著響應(yīng)者鏈條向上傳遞,將事件叫個(gè)上一個(gè)相應(yīng)者進(jìn)行處理

一般事件的傳遞是從父控件傳遞到子控件的

如果父控件接受不到觸摸事件,那么子控件就不可能接收到觸摸事件 UIView不能接收觸摸事件的三種情況:

1.不接受用戶交互:userInteractionEnabled = NO;

2.隱藏:hidden = YES;

3.透明:alpha = 0.0~0.01

用戶的觸摸事件首先會(huì)由系統(tǒng)截獲,進(jìn)行包裝處理等。? 然后遞歸遍歷所有的view,進(jìn)行碰觸測(cè)試(hitTest),直到找到可以處理事件的view。? - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system ?

該方法會(huì)首先在application的keyWindow上調(diào)用(UIWindow也是UIView的子類),并且該方法的返回值將被用來處理事件。如果這個(gè)view(無論是window還是普通的UIView) 的userInteractionEnabled屬性被設(shè)置為NO,則它的hitTest:永遠(yuǎn)返回nil,這意味著它和它的子視圖沒有機(jī)會(huì)去接收和處理事件。如果userInteractionEnabled屬性為YES,則會(huì)通過該方法- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;// default returns YES if point is in bounds先判斷產(chǎn)生觸摸的point是否發(fā)生在自己的bounds內(nèi),如果沒有也將返回nil;如果point在自己的范圍內(nèi),則會(huì)為自己的每個(gè)子視圖調(diào)用hitTest:方法,只要有一個(gè)子視圖通過這個(gè)方法返回一個(gè)UIView對(duì)象,那么整個(gè)方法就一層一層地往上返回;如果沒有子視圖返回UIView對(duì)象,則父視圖將會(huì)把自己返回。

大致的過程application –> window –> root view –>……–>lowest view

響應(yīng)者鏈

響應(yīng)者鏈條其實(shí)就是很多響應(yīng)者對(duì)象(繼承自UIResponder的對(duì)象)一起組合起來的鏈條稱之為響應(yīng)者鏈條

一般默認(rèn)做法是控件將事件順著響應(yīng)者鏈條向上傳遞,將事件交給上一個(gè)響應(yīng)者進(jìn)行處理。那么如何判斷當(dāng)前響應(yīng)者的上一個(gè)響應(yīng)者是誰呢?有以下兩個(gè)規(guī)則:

1.判斷當(dāng)前是否是控制器的View,如果是控制器的View,上一個(gè)響應(yīng)者就是控制器

2.如果不是控制器的View,上一個(gè)響應(yīng)者就是父控件

當(dāng)有view能夠處理觸摸事件后,開始響應(yīng)事件。 系統(tǒng)會(huì)調(diào)用view的以下方法:

- (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;? 可以多對(duì)象共同響應(yīng)事件。只需要在以上方法重載中調(diào)用super的方法。? 大致的過程initial view –>super view –> …..–> view controller –> window –> Application? 需要特別注意的一點(diǎn)是,傳遞鏈中時(shí)沒有controller的,因?yàn)閏ontroller本身不具有大小的概念。但是響應(yīng)鏈中是有controller的,因?yàn)閏ontroller繼承自UIResponder。

UIApplication–>UIWindow–>遞歸找到最合適處理的控件–>控件調(diào)用touches方法–>判斷是 否實(shí)現(xiàn)touches方法–>沒有實(shí)現(xiàn)默認(rèn)會(huì)將事件傳遞給上一個(gè)響應(yīng)者–>找到上一個(gè)響應(yīng)者–>找不到方法作廢

PS:利用響應(yīng)者鏈條我們可以通過調(diào)用touches的super 方法,讓多個(gè)響應(yīng)者同時(shí)響應(yīng)該事件。

最后編輯于
?著作權(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)容

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