詳解iOS觸摸事件與手勢識別

iOS最常見的是觸摸事件Touch Events燃异。觸摸事件除了是view來處理吴裤,還有高級的手勢可以處理缸兔。所以日裙,本文分別來講講觸摸事件和手勢,并結合例子講講兩者混合使用的問題惰蜜。

UITouch對象

一個手指第一次點擊屏幕昂拂,就會生成一個UITouch對象,到手指離開時銷毀抛猖。當我們有多個手指觸摸屏幕時,會生成多個UITouch對象财著。UITouch對象可以表明觸摸的位置联四、狀態(tài)。

UIEvent對象

一個UIEvent對象代表iOS的一個事件撑教。一個觸摸事件定義為第一個手指開始觸摸屏幕到最后一個手指離開屏幕朝墩。所以,一個UIEvent對象實際上對應多個UITouch對象伟姐。

響應鏈

響應鏈可以理解為一種虛擬的鏈表收苏,每一個節(jié)點是一個UIResponder對象。UIResponder是事件接收與處理的基類愤兵,UIApplication鹿霸、UIViewController和UIView都繼承自UIResponder。UIResponder提供了幾個事件處理的方法:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

UIResponder對象之間的聯(lián)系靠nextResponder指針秆乳。

#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly, nullable) UIResponder *nextResponder;
#else
- (nullable UIResponder*)nextResponder;
#endif

一個觸摸事件到達真正處理它的對象時經(jīng)過了一個搜索路徑懦鼠,這就是響應鏈的一部分。事件沿著這個響應鏈一直傳遞,直到碰到可以處理這個事件的UIResponder對象或者到達響應鏈的末尾(UIApplication)葛闷。
響應鏈的構造規(guī)則如下:

  1. 程序啟動時憋槐,UIApplication會生成一個單例,并會關聯(lián)一個APPDelegate淑趾。APPDelegate作為整個響應鏈的根建立起來阳仔,UIApplication的nextResponser為APPDelegate。
  2. 程序啟動后扣泊,任何的UIWindow被創(chuàng)建時近范,UIWindow內(nèi)部都會把nextResponser設置為UIApplication單例。
  3. UIWindow初始化rootViewController, rootViewController的nextResponser會設置為UIWindow延蟹。
  4. UIViewController初始化View评矩,View的nextResponser會設置為rootViewController。
  5. AddSubView時阱飘,如果subView不是ViewController的View,那么subView的nextResponser會被設置為superView斥杜。否則就是 subView -> subView.VC ->superView。



    有了這個響應鏈沥匈,事件就可以按照這個路徑逐級傳遞了蔗喂。當前的對象不能處理這個事件,就交給nextResponser高帖,一直到UIApplication單例缰儿。如果仍然不能處理,就丟棄散址。

Hit-Testing

當我們觸摸屏幕時乖阵,到底應該由哪個對象最先響應這個事件呢?這就需要去探測预麸,這個過程稱為Hit-Testing瞪浸,最后的結果稱為hit-test view。涉及到兩個方法是:

//先判斷點是否在View內(nèi)部吏祸,然后遍歷subViews
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; 
//判斷點是否在這個View內(nèi)部
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

Hit-Testing是一個遞歸的過程默终,每一步監(jiān)測觸摸位置是否在當前view中,如果是犁罩,就遞歸監(jiān)測subviews齐蔽;否則,返回nil床估。
遞歸的根節(jié)點是UIWindow含滴,對subviews的遍歷順序按照 后添加的先遍歷 原則。

手勢識別

手勢是Apple提供的更高級的事件處理技術丐巫,可以完成更多更復雜的觸摸事件谈况,比如旋轉勺美、滑動、長按等碑韵。
手勢綁定到一個View上赡茸,一個View上可以綁定多個手勢。
UIGestureRecognizer同UIResponder一樣也有四個方法:

//UIGestureRecognizer
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

手勢會在以上四個方法中去對手勢的State做更改祝闻,手勢的State表明當前手勢是識別還是失敗等等占卧。比如單擊手勢會在touchesBegan 時記錄點擊位置,然后在touchesEnded判斷點擊次數(shù)联喘、時間华蜒、是否移動過,最后得出否識別該手勢豁遭。這幾個方法一般在自定義手勢里面使用叭喜。

手勢識別與事件響應混用

1 觸摸事件首先傳遞到手勢上,如果手勢識別成功蓖谢,就會取消事件的繼續(xù)傳遞捂蕴,否則,事件會被響應鏈處理闪幽。具體地啥辨,系統(tǒng)維持了與響應鏈關聯(lián)的所有手勢,事件首先發(fā)給這些手勢沟使,然后再發(fā)給響應鏈委可。
2 在iOS 6.0 或以后版本中渊跋,默認控件操作方法會阻斷重復手勢的識別行為腊嗡。
一個按鈕的默認操作是一個單擊。如果你有一個單擊手勢識別綁定到一個按鈕的父視圖上拾酝,然后用戶點擊該按鈕燕少,最后按鈕的操作方法接收觸摸事件而不是手勢識別。 它只用于手勢識別跟一個控件的默認操作重復時蒿囤。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末客们,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子材诽,更是在濱河造成了極大的恐慌底挫,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脸侥,死亡現(xiàn)場離奇詭異建邓,居然都是意外死亡,警方通過查閱死者的電腦和手機睁枕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門官边,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沸手,“玉大人,你說我怎么就攤上這事注簿∑跫” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵诡渴,是天一觀的道長捐晶。 經(jīng)常有香客問我,道長玩徊,這世上最難降的妖魔是什么租悄? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮恩袱,結果婚禮上泣棋,老公的妹妹穿的比我還像新娘。我一直安慰自己畔塔,他們只是感情好潭辈,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澈吨,像睡著了一般把敢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谅辣,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天修赞,我揣著相機與錄音,去河邊找鬼桑阶。 笑死柏副,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蚣录。 我是一名探鬼主播割择,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萎河!你這毒婦竟也來了荔泳?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤虐杯,失蹤者是張志新(化名)和其女友劉穎玛歌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擎椰,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡支子,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了确憨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译荞。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓤的,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吞歼,到底是詐尸還是另有隱情圈膏,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布篙骡,位于F島的核電站稽坤,受9級特大地震影響,放射性物質發(fā)生泄漏糯俗。R本人自食惡果不足惜尿褪,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望得湘。 院中可真熱鬧杖玲,春花似錦、人聲如沸淘正。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸿吆。三九已至囤采,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惩淳,已是汗流浹背蕉毯。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留思犁,地道東北人代虾。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像抒倚,于是被迫代替她去往敵國和親褐着。 傳聞我的和親對象是個殘疾皇子坷澡,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容