浅析iOS中的触摸事件
一、什么是響應(yīng)者對象?
在 iOS中不是任何對象都能處理事件,只有繼承了UIResponder的對象才能接收并處理事件。我們稱之為“響應(yīng)者對象”。UIApplication、UIViewController、UIView都繼承自UIResponder,因此它們都是響應(yīng)者對象,都能夠接收并處理事件。
二、為什么說繼承了 UIResponder 就能夠處理事件?
因?yàn)樵赨IResponder內(nèi)部提供了以下方法來處理事件:
-
監(jiān)聽 UIView 的觸摸事件,會(huì)調(diào)用以下方法:
//一根或者多根手指在view上移動(dòng)時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用view的touchesMoved方法//(隨著手指的移動(dòng),會(huì)持續(xù)調(diào)用該方法,也就是說這個(gè)方法會(huì)調(diào)用很多次)- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
//一根或者多根手指離開view,系統(tǒng)會(huì)自動(dòng)調(diào)用view的touchesEnded方法- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
//當(dāng)觸摸序列被諸如電話呼入這樣的系統(tǒng)事件所取消時(shí),系統(tǒng)會(huì)調(diào)用touchesCancelled方法- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
-
加速計(jì)事件會(huì)調(diào)用
-
遠(yuǎn)程控制事件會(huì)調(diào)用
想要監(jiān)聽UIViiew的觸摸事件,首先要自定義UIView,只有實(shí)現(xiàn)了UIResponder的事件方法才能夠監(jiān)聽事件,?touches 中存放的都是 UITouch 對象。
三、觸摸事件中的 UITouch
當(dāng)用戶用一根手指觸摸屏幕時(shí),會(huì)創(chuàng)建一個(gè)與手指相關(guān)聯(lián)的 UITouch 對象,一根手指對應(yīng)一個(gè) UITouch 對象。
-
UITouch 的作用
-
保存跟手指有關(guān)的信息,比如觸摸的位置、時(shí)間、階段
-
-
當(dāng)手指移動(dòng)時(shí),系統(tǒng)會(huì)更新同一個(gè)UITouch對象,使之能夠一直保存該手指在的觸摸位置
-
當(dāng)手指離開屏幕時(shí),系統(tǒng)會(huì)銷毀相應(yīng)的UITouch對象
-
UITouch 的方法
?
?
四、觸摸事件中的 UIEvent
UIEvent 稱為事件對象,負(fù)責(zé)記錄事件產(chǎn)生的時(shí)刻和類型,每產(chǎn)生一個(gè)事件,就會(huì)產(chǎn)生一個(gè) UIEvent 對象。
在 UIEvent 中提供了相應(yīng)的方法可以獲取在某個(gè) View 上面的觸摸對象(UITouch)。
在一次完整的觸摸過程中,至少會(huì)經(jīng)歷開始、移動(dòng)、結(jié)束三個(gè)狀態(tài),在觸摸事件處理方法中,都有?touches?和?event兩個(gè)參數(shù)。
觸摸事件的總結(jié):
一次完整的觸摸過程中,只會(huì)產(chǎn)生一個(gè)事件對象,4個(gè)觸摸方法都是同一個(gè) event 參數(shù)。
如果兩根手指同時(shí)觸摸一個(gè)view,那么view只會(huì)調(diào)用一次touchesBegan:withEvent:方法,touches參數(shù)中裝著2個(gè)UITouch對象。
如果這兩根手指一前一后分開觸摸同一個(gè)view,那么view會(huì)分別調(diào)用2次touchesBegan:withEvent:方法,并且每次調(diào)用時(shí)的touches參數(shù)中只包含一個(gè)UITouch對象。
根據(jù)touches中UITouch的個(gè)數(shù)可以判斷出是單點(diǎn)觸摸還是多點(diǎn)觸摸。
?
第一步 尋找發(fā)生觸摸的視圖
第二步 傳遞和處理觸摸事件:UIResponder(響應(yīng)者)
檢測的目的是為了找到觸摸是發(fā)生在哪個(gè)視圖上(UIView)。這個(gè)檢測的順序是從底向上的檢測過程。首先UIApplication會(huì)傳遞給UIWindow,然后再由UIWindow傳遞給頂級的視圖,頂級視圖會(huì)進(jìn)一步遍歷其所有的subviews。UIView有個(gè)函數(shù)叫hitTest,如果觸摸事件是發(fā)生在該視圖中,則該函數(shù)會(huì)返回非空UIView;然后該視圖遞歸其subviews,最后發(fā)現(xiàn)最終的subview。
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event這里有個(gè)特殊情況,如果一個(gè)視圖被設(shè)置為user-interaction = NO,那么hitTest會(huì)返回空指針。某些繼承自uiview的組件默認(rèn)user-interaction = NO,比方說UIImageView。
第一步驟結(jié)束一定能找一個(gè)hit-test view,然后就開始調(diào)用其UIResponder->touches*函數(shù)進(jìn)行處理;
如果我們不重寫touches函數(shù)的話,默認(rèn)會(huì)調(diào)用self->nextResponder->touches*進(jìn)一步把觸摸事件往下進(jìn)行傳遞。每個(gè)responder都有個(gè)nextResponder,這就組成了一個(gè)響應(yīng)者鏈(responder?chain)。值得注意的是:
1、如果我們重寫touches*函數(shù)時(shí),不調(diào)用[super touches*]的話,那么事件就不會(huì)繼續(xù)往下傳遞;
2、UIViewController也繼承自UIResponder,所以響應(yīng)鏈中除了有視圖,也有視圖控制器。所以視圖控制區(qū)中,也可以實(shí)現(xiàn)touches*函數(shù)。
3、關(guān)于響應(yīng)鏈的形成:看起來響應(yīng)鏈?zhǔn)欠浅€(gè)錯(cuò)綜復(fù)雜的數(shù)據(jù)鏈,其實(shí)它很簡單。每個(gè)responder只關(guān)心其nextResponder就可以了。而關(guān)于nextResponder的賦值過程我推測是這樣的:當(dāng)UIViewcontroller初始化時(shí),將其關(guān)聯(lián)的視圖的nextResponder設(shè)為自己;當(dāng)一個(gè)子視圖add時(shí),就自動(dòng)將其nextResponder設(shè)為其父視圖。
?
總結(jié)
以上是生活随笔為你收集整理的浅析iOS中的触摸事件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GitLab安装配置使用总结
- 下一篇: shell脚本练习(12.8)