iOS-事件處理(觸摸事件)

事件

移動(dòng)應(yīng)用中常用的事件
 1. 觸摸事件。
 2. 加速計(jì)事件。例如:手機(jī)搖一搖
 3. 遠(yuǎn)程控制事件。例如:耳機(jī)控制
常用事件.png
處理事件的條件:
  • 在iOS中,不是任何對(duì)象都能處理事件,只有繼承了UIResponder的對(duì)象才能接收并處理事件,稱(chēng)之為“響應(yīng)者對(duì)象”。
  • UIApplication,UIViewController,UIView都繼承自UIResponder,因此它們都是響應(yīng)者對(duì)象,都能接收并處理事件。
處理方法:
UIResponder內(nèi)部提供的事件處理方法,可以在類(lèi)中重寫(xiě)下列方法來(lái)處理事件:
// 觸摸事件
  - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

// 加速計(jì)事件
  - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
  - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
  - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

//遠(yuǎn)程控制事件

  - (void)remoteControlReceivedWithEvent:(UIEvent *)event;

觸摸事件

UIView的觸摸事件處理

UIView是UIResponder的子類(lèi),通過(guò)覆蓋下列四個(gè)方法處理觸摸事件
覆蓋下列方法后,系統(tǒng)會(huì)自動(dòng)調(diào)用來(lái)進(jìn)行事件的處理

 一根或者多根手指開(kāi)始觸摸View:                     
  - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

 一根或者多根手指在View移動(dòng),隨著手指的移動(dòng),系統(tǒng)會(huì)不斷調(diào)用此方法:    
  - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;   
            
一根或者多根手指離開(kāi)View:
   - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

  觸摸結(jié)束之前,某個(gè)系統(tǒng)事件(例如電話呼入)打斷觸摸過(guò)程
   - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

UITouch

  • 當(dāng)用戶用一根手指觸摸屏幕時(shí),會(huì)創(chuàng)建一個(gè)與手指相關(guān)聯(lián)的UITouch對(duì)象。
  • 一根手指對(duì)應(yīng)一個(gè)UITouch對(duì)象,多根手指觸摸時(shí),會(huì)創(chuàng)建多個(gè)UITouch對(duì)象。
UITouch的作用:
  • 保存著跟手指的相關(guān)的信息,比如觸摸的位置,時(shí)間,階段。
  • 當(dāng)手指移動(dòng)時(shí),系統(tǒng)會(huì)更新同一個(gè)UITouch對(duì)象,使之能夠一直保存該手指的觸位置。
  • 當(dāng)手指離開(kāi)屏幕時(shí),系統(tǒng)會(huì)銷(xiāo)毀相應(yīng)的UITouch對(duì)象。
UITouch的常用屬性
  //觸摸產(chǎn)生時(shí)所處的窗口
  @property(nullable,nonatomic,readonly,strong) UIWindow *window;

  //觸摸產(chǎn)生時(shí)所處的視圖
  @property(nullable,nonatomic,readonly,strong) UIView *view;

  //記錄了觸摸事件產(chǎn)生時(shí)或變化時(shí)的時(shí)間,單位時(shí)秒
  @property(nonatomic,readonly) NSTimeInterval timestamp;

  //當(dāng)前觸摸事件所處的狀態(tài)
  @property(nonatomic,readonly) UITouchPhase phase;

  //短時(shí)間內(nèi)點(diǎn)擊屏幕的次數(shù),可以根據(jù)此屬性判斷單擊,雙擊,或更多點(diǎn)擊
  @property(nonatomic,readonly) NSUInteger tapCount;

  //iOS9開(kāi)始支持的屬性,觸摸類(lèi)型,包括直接觸摸,間接觸摸,觸控筆觸摸
  @property(nonatomic,readonly) UITouchType type;
  typedef NS_ENUM(NSInteger, UITouchType) {
      UITouchTypeDirect, //直接觸摸
      UITouchTypeIndirect, //間接觸摸
      UITouchTypeStylus, //觸控筆觸摸
  };

  @property(nonatomic,readonly) CGFloat majorRadius //觸摸的半徑;
UITouch的常用方法
 //返回觸摸點(diǎn)在view上的位置,針對(duì)view的坐標(biāo)系統(tǒng)(以view的左上角為原點(diǎn)),傳入的view為空時(shí),返回的觸摸點(diǎn)在UIWindow的位置
 - (CGPoint)locationInView:(nullable UIView *)view;

 //返回前一個(gè)觸摸點(diǎn)的位置
 - (CGPoint)previousLocationInView:(nullable UIView *)view;

 //精確的觸摸點(diǎn)位置 iOS9.1之后
 - (CGPoint)preciseLocationInView:(nullable UIView *)view   NS_AVAILABLE_IOS(9_1);

 //精確的前一個(gè)觸摸點(diǎn)的位置 iOS9.1之后
 - (CGPoint)precisePreviousLocationInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);

UIEvent

  • 每產(chǎn)生一個(gè)事件,就會(huì)產(chǎn)生一個(gè)UIEvent對(duì)象,稱(chēng)為事件對(duì)象,記錄事件產(chǎn)生的時(shí)刻和類(lèi)型。
UIEvent常用屬性
 //事件類(lèi)型
 @property(nonatomic,readonly) UIEventType     type NS_AVAILABLE_IOS(3_0);
 @property(nonatomic,readonly) UIEventSubtype  subtype NS_AVAILABLE_IOS(3_0);

 //事件產(chǎn)生的時(shí)間
 @property(nonatomic,readonly) NSTimeInterval  timestamp;
UIEvent常用方法
 //獲得窗口上的UITouch對(duì)象
 - (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;

 //獲得view上的UITouch對(duì)象
 - (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;

touches和event參數(shù)

一次完整的觸摸過(guò)程,會(huì)經(jīng)歷3個(gè)狀態(tài):

 觸摸開(kāi)始:                     
  - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

 觸摸移動(dòng):   
  - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;   
            
 觸摸結(jié)束:
  - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

 觸摸消失(可能會(huì)經(jīng)歷):
  - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  • 4個(gè)觸摸事件處理方法中,都有NSSet *touches和UIEvent *event兩個(gè)參數(shù)
  • 一次完整的觸摸過(guò)程,只會(huì)產(chǎn)生一個(gè)事件對(duì)象,4個(gè)觸摸方法都是同一個(gè)event參數(shù)。
  • 如果兩根手指同時(shí)觸摸一個(gè)view,那么view只會(huì)調(diào)用一次 touchesBegan:withEvent:方法,touches參數(shù)中裝著2個(gè)UITouch對(duì)象。
  • 如果兩根手指一前一后觸摸同一個(gè)view,那么view會(huì)分別調(diào)用兩次touchesBegan:withEvent:方法,并且每次調(diào)用時(shí)的touches參數(shù)只包含一個(gè)UITouch對(duì)象。
  • 根據(jù)touches中的UITouch的個(gè)數(shù)可以判斷出是單點(diǎn)觸摸還是多點(diǎn)觸摸

事件的產(chǎn)生和傳遞(觸摸事件)

1.觸摸事件發(fā)生后,系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中。
2.UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,并將事件分發(fā)下去以便處理,通常,先發(fā)送事件給應(yīng)用程序的主窗口(keyWindow)。
3.主窗口會(huì)在視圖層次結(jié)構(gòu)中,找到一個(gè)最合適的視圖來(lái)處理事件,這也是整個(gè)事件處理過(guò)程中的第一步。
4.找到合適的視圖后,就會(huì)調(diào)用視圖控件的touches方法來(lái)做具體的事件處理

即: 觸摸(事件發(fā)生) ——> UIApplication管理的事件隊(duì)列 ——> 主窗口(keyWindow) ——> 合適的視圖 ——> 視圖通過(guò)方法來(lái)處理事件


事件傳遞.png
  • 找到做合適的控件兩個(gè)步驟:
    1.自己是否能接收事件。 2.觸摸點(diǎn)是否在自己身上。

  • 如果父控件不能接收事件,那么子控件就不可能接收到事件。
    UIView不能接收觸摸事件的三種情況:
    1.不接收用戶交互
    屬性u(píng)serInteractionEnabled = NO;
    2.視圖隱藏
    屬性hidden = YES;
    3.透明
    屬性alpha = 0.0 ~ 0.01;
    PS:UIImageView的userInteractionEnabled 默認(rèn)為 NO,因此UIImageView以及它的子控件默認(rèn)是不能接收事件的。

  • 如果沒(méi)有合適的響應(yīng)者,系統(tǒng)將丟棄這一事件。

響應(yīng)者鏈條

  • 響應(yīng)者鏈條:響應(yīng)者鏈條是有多個(gè)響應(yīng)者對(duì)象連接起來(lái)的鏈條。(繼承自UIRespngder,能夠處理事件的對(duì)象叫做響應(yīng)者對(duì)象)
  • 好處:通過(guò)響應(yīng)者鏈條,能夠讓多個(gè)控件處理同一個(gè)觸摸事件。(在touches方法內(nèi)部,用super調(diào)用touches方法)
  • 用戶點(diǎn)擊屏幕后產(chǎn)生的一個(gè)觸摸事件,經(jīng)過(guò)一系列的傳遞過(guò)程之后,會(huì)找到最合適的控件來(lái)處理這個(gè)事件。
響應(yīng)者鏈條.png
響應(yīng)者鏈條的事件傳遞過(guò)程:
  • 響應(yīng)者鏈條的事件傳遞過(guò)程的順序與觸摸事件的傳遞過(guò)程相反。
  • 響應(yīng)者鏈條的傳遞由最合適的控件開(kāi)始,由子視圖往父視圖傳遞。
  • 如果view的控制器存在,就傳遞給控制器,如果控制器不存在,就傳遞給其他父視圖。
  • 在視圖層次結(jié)構(gòu)的最頂級(jí)視圖,如果不能處理收到的事件或消息,則將事件或消息給window處理。
  • 如果window對(duì)象也不處理,則將事件或消息傳遞給UIApplication對(duì)象。
  • 如果UIApplication對(duì)象也不能處理,則將其丟棄。
  • 找到最合適的控件之后,會(huì)調(diào)用touches方法來(lái)做具體的事件處理。
    touchesBegan……
    touchesMoves……
    touchesEnded……
    這些touches方法的默認(rèn)做法是將事件順著響應(yīng)者鏈條向上傳遞,將事件交給上一個(gè)響應(yīng)者處理。

手勢(shì)識(shí)別器

  • 之前處理觸摸事件的做法:
    如果想監(jiān)聽(tīng)一個(gè)view上的觸摸事件
    1.自定義一個(gè)view。
    2.實(shí)現(xiàn)view的touches方法,在方法內(nèi)部實(shí)現(xiàn)具體代碼來(lái)處理。
    缺點(diǎn):
    1.必須自定義view。
    2.由于是在view內(nèi)部的touches方法中堅(jiān)挺觸摸事件,因此默認(rèn)情況下,無(wú)法讓其他外界對(duì)象監(jiān)聽(tīng)view的觸摸事件。
    3.不容易區(qū)分用戶的具體手勢(shì)行為。

iOS3.2之后,蘋(píng)果推出手勢(shì)識(shí)別功能(Gesture Recognizer)。

  • 如果要完成手勢(shì)識(shí)別,必須借助于手勢(shì)識(shí)別器—UIGestureRecognizer
    UIGestureRecognizer是一個(gè)抽象類(lèi),定義了所有手勢(shì)的基本行為,使用它的子類(lèi)才能處理具體的手勢(shì)。
    UITapGestureRecognizer(敲擊)
    UIPinchGestureRecognizer(捏合,用于縮放)
    UIPanGestureRecognizer(拖拽)
    UISwipeGestureRecognizer(輕掃)
    UIRotationGestureRecognizer(旋轉(zhuǎn))
    UILongGestureRecognizer(長(zhǎng)按)
手勢(shì)識(shí)別器的使用:
    //1.創(chuàng)建敲擊手勢(shì)識(shí)別器
    UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] init];
    
    //2.給要進(jìn)行處理觸摸事件的view添加手勢(shì)識(shí)別,這里給self.view添加手勢(shì)識(shí)別
    [self.view addGestureRecognizer:tapGR];
    
    //3.添加監(jiān)聽(tīng)方法
    tapGR addTarget:self action:@selector(tapMethod:) //實(shí)現(xiàn)tapMethod:方法來(lái)處理具體的操作
最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點(diǎn)擊了?糾結(jié)于如何實(shí)現(xiàn)這個(gè)奇葩響應(yīng)需求?亦或是...
    Lotheve閱讀 59,560評(píng)論 51 604
  • 在iOS開(kāi)發(fā)中經(jīng)常會(huì)涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺(jué)總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,249評(píng)論 4 26
  • -- iOS事件全面解析 概覽 iPhone的成功很大一部分得益于它多點(diǎn)觸摸的強(qiáng)大功能,喬布斯讓人們認(rèn)識(shí)到手機(jī)其實(shí)...
    翹楚iOS9閱讀 3,221評(píng)論 0 13
  • 響應(yīng)者對(duì)象 在iOS中不是任何對(duì)象都能處理事件,只有繼承了UIResponder的對(duì)象才能接收并處理事件。我們稱(chēng)之...
    JonesCxy閱讀 809評(píng)論 0 0
  • iOS中有三類(lèi)事件:UIEventTypeTouches觸摸事件、 UIEventTypeMotion “動(dòng)作”事...
    WeiHing閱讀 37,401評(píng)論 7 69

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