觸摸事件的處理原理如下:
1.當(dāng)用戶點(diǎn)擊屏幕時(shí)蛮放,會(huì)產(chǎn)生一個(gè)觸摸事件赡艰,系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中
2.UIApplication會(huì)從事件隊(duì)列中取出最前面的事件進(jìn)行分發(fā)以便處理,通常,先發(fā)送事件給應(yīng)用程序的主窗口(UIWindow)
3. 主窗口會(huì)調(diào)用hitTest:withEvent:方法在視圖(UIView)層次結(jié)構(gòu)中找到一個(gè)最合適的UIView來處理觸摸事件
(hitTest:withEvent:其實(shí)是UIView的一個(gè)方法,UIWindow繼承自UIView,因此主窗口UIWindow也是屬于視圖的一種)
4.hitTest:withEvent:方法大致處理流程是這樣的:
首先調(diào)用當(dāng)前視圖的pointInside:withEvent:方法判斷觸摸點(diǎn)是否在當(dāng)前視圖內(nèi):
若pointInside:withEvent:方法返回NO辽狈,說明觸摸點(diǎn)不在當(dāng)前視圖內(nèi),則當(dāng)前視圖的hitTest:withEvent:返回nil
若pointInside:withEvent:方法返回YES呛牲,說明觸摸點(diǎn)在當(dāng)前視圖內(nèi)刮萌,則遍歷當(dāng)前視圖的所有子視圖(subviews),調(diào)用子視圖的hitTest:withEvent:方法重復(fù)前面的步驟娘扩,子視圖的遍歷順序是從top到bottom着茸,即從subviews數(shù)組的末尾向前遍歷,直到有子視圖的hitTest:withEvent:方法返回非空對(duì)象或者全部子視圖遍歷完畢:
?若第一次有子視圖的hitTest:withEvent:方法返回非空對(duì)象,則當(dāng)前視圖的hitTest:withEvent:方法就返回此對(duì)象琐旁,處理結(jié)束
若所有子視圖的hitTest:withEvent:方法都返回nil涮阔,則當(dāng)前視圖的hitTest:withEvent:方法返回當(dāng)前視圖自身(self)
最終,這個(gè)觸摸事件交給主窗口的hitTest:withEvent:方法返回的視圖對(duì)象去處理灰殴。
拿到這個(gè)UIView后敬特,就調(diào)用該UIView的touches系列方法。
5.消息處理過程,在找到的那個(gè)視圖里處理伟阔,處理完后根據(jù)需要辣之,利用響應(yīng)鏈nextResponder可將消息往下一個(gè)響應(yīng)者傳遞。
UIAppliactionDelegate <- UIWindow <- UIViewController <- UIView <- UIView
【注意】:要理解的有三點(diǎn):
1皱炉、iOS判斷哪個(gè)界面能接受消息是從View層級(jí)結(jié)構(gòu)的父View向子View傳遞怀估,即樹狀結(jié)構(gòu)的根節(jié)點(diǎn)向葉子節(jié)點(diǎn)遞歸傳遞。
2娃承、hitTest和pointInside成對(duì)奏夫,且hitTest會(huì)調(diào)用pointInside怕篷。
3历筝、iOS的消息處理是,當(dāng)消息被人處理后默認(rèn)不再向父層傳遞廊谓。