iOS中加載的時(shí)候會先執(zhí)行main函數(shù)
int main(int argc, charchar * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
根據(jù)main函數(shù)的參數(shù)加載UIApplication->AppDelegate->UIWindow->UIViewController->superView->subViews
關(guān)系為:UIApplication.keyWindow.rootViewController.view.subView
事件傳遞機(jī)制:
1.當(dāng)iOS程序中發(fā)生觸摸事件后纱昧,系統(tǒng)會將事件加入到UIApplication管理的一個(gè)任務(wù)隊(duì)列中
2.UIApplication將處于任務(wù)隊(duì)列最前端的事件向下分發(fā)安疗。即UIWindow鞭衩。
3.UIWindow將事件向下分發(fā)收恢,即UIView宫蛆。
4.UIView首先看自己是否能處理事件唾琼,觸摸點(diǎn)是否在自己身上痘系。如果能妇穴,那么繼續(xù)尋找子視圖灸姊。
5.遍歷子控件拱燃,重復(fù)以上兩步。
6.如果沒有找到力惯,那么自己就是事件處理者碗誉。如果
7.如果自己不能處理召嘶,那么不做任何處理。
其中 UIView不接受事件處理的情況主要有以下三種
1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES
以下來自網(wǎng)絡(luò):
響應(yīng)者鏈條概念: iOS系統(tǒng)檢測到手指觸摸(Touch)操作時(shí)會將其打包成一個(gè)UIEvent對象哮缺,并放入當(dāng)前活動Application的事件隊(duì)列弄跌,單例的UIApplication會從事件隊(duì)列中取出觸摸事件并傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點(diǎn)所在的視圖(View)尝苇,即需要將觸摸事件傳遞給其處理的視圖铛只,這個(gè)過程稱之為hit-test view。
UIResponder 是所有響應(yīng)對象的基類糠溜,在UIResponder類中定義了處理上述各種事件的接口淳玩。我們熟悉的 UIApplication、 UIViewController非竿、 UIWindow 和所有繼承自UIView的UIKit類都直接或間接的繼承自UIResponder蜕着,所以它們的實(shí)例都是可以構(gòu)成響應(yīng)者鏈的響應(yīng)者對象。
UIWindow實(shí)例對象會首先在它的內(nèi)容視圖上調(diào)用hitTest:withEvent:红柱,此方法會在其視圖層級結(jié)構(gòu)中的每個(gè)視圖上調(diào)用pointInside:withEvent:(該方法用來判斷點(diǎn)擊事件發(fā)生的位置是否處于當(dāng)前視圖范圍內(nèi)承匣,以確定用戶是不是點(diǎn)擊了當(dāng)前視圖),如果pointInside:withEvent:返回YES锤悄,則繼續(xù)逐級調(diào)用韧骗,直到找到touch操作發(fā)生的位置,這個(gè)視圖也就是要找的hit-test view零聚。
hitTest:withEvent:方法的處理流程如下:
首先調(diào)用當(dāng)前視圖的pointInside:withEvent:方法判斷觸摸點(diǎn)是否在當(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)的過程
UIApplication --> UIWindow --> 遞歸找到最適合處理事件的控件
控件調(diào)用touches方法 --> 判斷是否實(shí)現(xiàn)touches方法 --> 沒有實(shí)現(xiàn)默認(rèn)會將事件傳遞給上一個(gè)響應(yīng)者 --> 找到上一個(gè)響應(yīng)者
PS:如果直到UIApplication都不響應(yīng),那么這個(gè)事件就被廢棄了措嵌。
1.響應(yīng)者鏈條:由很多響應(yīng)者鏈接在一起組合起來的一個(gè)鏈條
響應(yīng)者:繼承自UIResponder的對象稱之為響應(yīng)者對象
2.上一個(gè)響應(yīng)者(默認(rèn)做法是將事件順著響應(yīng)者鏈條向上傳遞躲叼,將事件交給上一個(gè)響應(yīng)者進(jìn)行處理)
如何判斷當(dāng)前響應(yīng)者的上一個(gè)響應(yīng)者是誰?
1>判斷當(dāng)前是否是控制器的View企巢,如果是枫慷,上一個(gè)響應(yīng)者就是控制器
2>如果當(dāng)前不是控制器的View,上一個(gè)響應(yīng)者就是父控件
3.響應(yīng)者鏈條有什么用?
可以讓一個(gè)觸摸事件發(fā)聲的時(shí)候讓多個(gè)響應(yīng)者同時(shí)響應(yīng)該事件
在子類的實(shí)現(xiàn)文件里的touchesBegan:方法里加上如下代碼即可
[super touchesBegan:touches withEvent:event]