響應(yīng)與控制 --- UIResponder及相關(guān)類

一、概述:

在iOS中事件一般分為三類在iOS 9后又添加了關(guān)于深按的事件:

  • 觸摸事件:通過(guò)觸摸或者手勢(shì)進(jìn)行觸發(fā)(如手指點(diǎn)擊、縮放);
  • 運(yùn)動(dòng)事件:通過(guò)加速器進(jìn)行觸發(fā)(如手機(jī)搖一搖功能);
  • 遠(yuǎn)程控制事件:通過(guò)其他遠(yuǎn)程設(shè)備觸發(fā)(例如耳機(jī)控制);
  • 深按事件 :通過(guò)深度按壓進(jìn)行觸發(fā)(一般用于遙控器)。

但是在iOS中并不是所有的類都能處理接收并事件,只有繼承自UIResponder類的對(duì)象才能處理事件,要處理特定類型的事件,響應(yīng)者必須覆蓋相應(yīng)的方法,UIResponder是用于響應(yīng)和處理事件的抽象界面。關(guān)于UIResponder類的繼承關(guān)系如下所示:

該圖只列出部分常見(jiàn)控件的繼承關(guān)系,還有些未列出,如遇到可自行查看~

二、關(guān)于UIResponder類

1、基礎(chǔ)屬性和方法:
  • nextResponder:返回響應(yīng)者鏈中的下一個(gè)響應(yīng)者,如果沒(méi)有下一個(gè)響應(yīng)者返回nil。
  • - (BOOL)canBecomeFirstResponder:返回一個(gè)布爾值,能否成為第一響應(yīng)者,默認(rèn)是NO。子類必須重寫此方法并返回YES以成為第一響應(yīng)者。
  • - (BOOL)becomeFirstResponder;:成為第一響應(yīng)者。調(diào)用此方法不能保證對(duì)象一定成為第一個(gè)響應(yīng)者(比如View)。另外,不要在非可視的活躍視圖上調(diào)用此方法??梢酝ㄟ^(guò)檢查其window屬性來(lái)確定視圖是否在屏幕上。如果該屬性包含有效的窗口,則它是活動(dòng)視圖層次結(jié)構(gòu)的一部分。如果該屬性是nil,該視圖不是有效的視圖層次結(jié)構(gòu)的一部分。
  • isFirstResponder:是否是第一響應(yīng)者。
  • canResignFirstResponder:能否取消第一響應(yīng)者身份,默認(rèn)是YES。
  • - (BOOL)resignFirstResponder;:取消第一響應(yīng)者身份。
2、響應(yīng)觸摸事件的方法:
  • - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;:// 觸摸開(kāi)始
  • - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;:// 按住不放開(kāi)拖動(dòng)
  • - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;:// 觸摸結(jié)束
  • - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;:// 觸摸取消(被動(dòng)),常見(jiàn)如被來(lái)電話打斷等
  • - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1); :// API解釋是:告知響應(yīng)者已經(jīng)收到了以前估計(jì)的屬性的更新值,或者不再期望更新。暫時(shí)不知道如何使用~
3、響應(yīng)深按事件的方法:
  • - (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event ;:// 當(dāng)物理按鈕被首次按下時(shí),告訴這個(gè)對(duì)象。
  • - (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event ;:// 當(dāng)與按壓相關(guān)聯(lián)的值發(fā)生變化時(shí),告知此對(duì)象。
  • - (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event ;:// 當(dāng)按鈕被釋放時(shí)告訴對(duì)象。
  • - (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event:// 當(dāng)系統(tǒng)事件(如低內(nèi)存警告))取消按壓事件時(shí),告知此對(duì)象。
4、響應(yīng)運(yùn)動(dòng)事件的方法:
  • - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event;:// 開(kāi)始加速的時(shí)候調(diào)用
  • - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event:// 加速結(jié)束的時(shí)候調(diào)用
  • - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event:// 系統(tǒng)發(fā)出取消加速計(jì)事件的時(shí)候調(diào)用
5、響應(yīng)遠(yuǎn)程控制事件的方法:
  • - (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event;:// 要允許遠(yuǎn)程控制事件的傳遞,必須調(diào)用UIApplication的beginReceivingRemoteControlEvents;的方法。要關(guān)閉遠(yuǎn)程控制事件的傳遞調(diào)用方法:endReceivingRemoteControlEvents??梢詸z查evevt參數(shù)中subtype屬性(UIEventSubtype結(jié)構(gòu)體類型)以確定預(yù)期的命令。

PS_Subtype:

typedef NS_ENUM(NSInteger, UIEventSubtype) {
    // available in iPhone OS 3.0
    UIEventSubtypeNone                              = 0,
    
    // for UIEventTypeMotion, available in iPhone OS 3.0
    UIEventSubtypeMotionShake                       = 1,
    
    // for UIEventTypeRemoteControl, available in iOS 4.0
    UIEventSubtypeRemoteControlPlay                 = 100, // 播放。
    UIEventSubtypeRemoteControlPause                = 101, // 暫停。
    UIEventSubtypeRemoteControlStop                 = 102, // 停止。
    UIEventSubtypeRemoteControlTogglePlayPause      = 103, // 播放或暫停切換,iphone抽屜中使用這個(gè)。
    UIEventSubtypeRemoteControlNextTrack            = 104, // 下一曲。(按耳機(jī)線控中間按鈕兩下)
    UIEventSubtypeRemoteControlPreviousTrack        = 105, // 上一曲。(按耳機(jī)線控中間按鈕三下)
    UIEventSubtypeRemoteControlBeginSeekingBackward = 106, // 快退開(kāi)始。(按耳機(jī)線控中間按鈕三下不要松開(kāi))
    UIEventSubtypeRemoteControlEndSeekingBackward   = 107,// 快退停止。
    UIEventSubtypeRemoteControlBeginSeekingForward  = 108, // 快進(jìn)開(kāi)始(按耳機(jī)線控中間按鈕兩下不要松開(kāi))
    UIEventSubtypeRemoteControlEndSeekingForward    = 109, // 快進(jìn)停止。
};
6、驗(yàn)證命令相關(guān)方法:

以下方法一般用于設(shè)置編輯菜單,就是長(zhǎng)按文本后彈出有復(fù)制、選擇等選項(xiàng)的菜單。

  • - (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender;:其中action標(biāo)識(shí)與命令關(guān)聯(lián)的方法的選擇器;sender為調(diào)用此方法的對(duì)象,對(duì)于編輯菜單命令,這是UIApplication對(duì)象。如果被action所標(biāo)識(shí)的命令應(yīng)該被啟用則返回YES或者應(yīng)該被禁用則返回NO。默認(rèn)返回YES。

  • - (nullable id)targetForAction:(SEL)action withSender:(nullable id)sender;:返回一個(gè)調(diào)用其操作方法執(zhí)行命令的對(duì)象。

三、關(guān)于UITouch類

當(dāng)用戶用一根手指觸摸屏幕時(shí),就會(huì)創(chuàng)建一個(gè)與手指相關(guān)聯(lián)的UITouch對(duì)象,可以這樣理解:一根手指對(duì)應(yīng)一個(gè)UITouch對(duì)象。UITouch的作用:表示在屏幕上發(fā)生的觸摸事件的位置,大小,移動(dòng)和力度(在支持3D Touch或Apple Pencil的設(shè)備上)的對(duì)象。當(dāng)手指移動(dòng)時(shí),系統(tǒng)會(huì)更新同一個(gè)UITouch對(duì)象,使之能夠一直保存該手指在的觸摸位置,當(dāng)手指離開(kāi)屏幕時(shí),系統(tǒng)會(huì)銷毀相應(yīng)的UITouch對(duì)象。

1、UITouch的四個(gè)枚舉類:

(1)、觸摸階段判斷類:UITouchPhase

typedef NS_ENUM(NSInteger, UITouchPhase) {
    UITouchPhaseBegan,             // 當(dāng)手指觸摸開(kāi)始時(shí)
    UITouchPhaseMoved,             // 當(dāng)手指在表面上移動(dòng)時(shí)
    UITouchPhaseStationary,        // 當(dāng)手指觸摸表面,但自上一個(gè)事件以來(lái)沒(méi)有移動(dòng)。
    UITouchPhaseEnded,             // 當(dāng)手指離開(kāi)表面時(shí)
    UITouchPhaseCancelled,         // 當(dāng)觸摸沒(méi)有結(jié)束,但是我們需要取消、停止跟蹤時(shí)(例如將設(shè)備放在臉上)
};

(2)、3D Touch 檢測(cè)類:UIForceTouchCapability

typedef NS_ENUM(NSInteger, UIForceTouchCapability) {
    UIForceTouchCapabilityUnknown = 0,        // 檢測(cè)失敗
    UIForceTouchCapabilityUnavailable = 1,    // 3D Touch不可用
    UIForceTouchCapabilityAvailable = 2       // 3D Touch可用
};

(3)、觸摸接觸類型類:UITouchType

typedef NS_ENUM(NSInteger, UITouchType) {
    UITouchTypeDirect,     // 手指直接觸摸(在屏幕上)
    UITouchTypeIndirect,   // 間接觸摸(不是屏幕)
    UITouchTypeStylus      // 觸摸筆
} NS_ENUM_AVAILABLE_IOS(9_0);

(4)、觸摸特性:UITouchProperties

typedef NS_OPTIONS(NSInteger, UITouchProperties) {
    UITouchPropertyForce = (1UL << 0),    //力度
    UITouchPropertyAzimuth = (1UL << 1),  //方位
    UITouchPropertyAltitude = (1UL << 2), //高度
    UITouchPropertyLocation = (1UL << 3), //位置
} NS_AVAILABLE_IOS(9_1);
2、UITouch的屬性和方法:
  • @property(nonatomic,readonly) NSTimeInterval timestamp; : 記錄觸摸事件產(chǎn)生或變化時(shí)的時(shí)間(s)

  • @property(nonatomic,readonly) UITouchPhase phase;:觸摸階段

  • @property(nonatomic,readonly) NSUInteger tapCount; :表示短時(shí)間內(nèi)輕擊屏幕的次數(shù)。

  • @property(nonatomic,readonly) UITouchType type NS_AVAILABLE_IOS(9_0);:觸摸類型

  • @property(nonatomic,readonly) CGFloat majorRadius NS_AVAILABLE_IOS(8_0);:觸摸半徑

  • @property(nonatomic,readonly) CGFloat majorRadiusTolerance NS_AVAILABLE_IOS(8_0);:觸摸半徑容差

  • @property(nullable,nonatomic,readonly,strong) UIWindow *window;:觸摸產(chǎn)生時(shí)所處的窗口。因?yàn)榇翱诳赡馨l(fā)生變化,當(dāng)前所在的窗口不一定是最開(kāi)始的窗口

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

  • @property(nullable,nonatomic,readonly,copy) NSArray <UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);`:正在接收觸摸對(duì)象的手勢(shì)集合

  • - (CGPoint)locationInView:(nullable UIView *)view;:觸摸位置的坐標(biāo) --- 表示觸摸在view這個(gè)視圖上的位置,這里返回的位置是針對(duì)view的坐標(biāo)系的。調(diào)用時(shí)傳入的view參數(shù)為空的話,返回的時(shí)觸摸點(diǎn)在整個(gè)窗口的位置

  • - (CGPoint)previousLocationInView:(nullable UIView *)view;:上一次觸摸的坐標(biāo)


  • - (CGPoint)preciseLocationInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);:觸摸的精確的坐標(biāo)

  • - (CGPoint)precisePreviousLocationInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);:精確的上一次觸摸的坐標(biāo)

  • @property(nonatomic,readonly) CGFloat force NS_AVAILABLE_IOS(9_0);:觸摸力度,1.0表示平均觸摸力

  • @property(nonatomic,readonly) CGFloat maximumPossibleForce NS_AVAILABLE_IOS(9_0);:最大的可能的觸摸力度

  • - (CGFloat)azimuthAngleInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);:返回在視圖中觸控筆的方位角。 僅適用于觸筆類型。 參數(shù)傳nil以獲得相對(duì)于觸摸窗口的方位角度。當(dāng)觸控筆的尖端觸摸屏幕時(shí),當(dāng)觸控筆的頂端(即尖端的相反端部)沿設(shè)備屏幕的正x軸指向時(shí),該屬性的值為0弧度。以此筆的0弧度位置,沿順時(shí)針?lè)较蛐D(zhuǎn)增加弧度,否者是負(fù)值。

  • - (CGVector)azimuthUnitVectorInView:(nullable UIView *)view NS_AVAILABLE_IOS(9_1);:指向方位角方向的單位矢量。 僅適用于觸筆類型。傳遞視圖參數(shù)的nil將返回相對(duì)于觸摸窗口的單位矢量。

  • @property(nonatomic,readonly) CGFloat altitudeAngle NS_AVAILABLE_IOS(9_1);:觸筆觸針的高度角,當(dāng)筆平行于平面時(shí),該值為0。當(dāng)筆垂直于平面時(shí),該值為M_PI/2。

  • @property(nonatomic,readonly) NSNumber * _Nullable estimationUpdateIndex NS_AVAILABLE_IOS(9_1);:此屬性包含當(dāng)前觸摸數(shù)據(jù)的唯一標(biāo)記,當(dāng)每個(gè)觸摸對(duì)象的觸摸特性發(fā)生變化時(shí),該值將會(huì)單獨(dú)增加,返回值是NSNumber 索引號(hào),關(guān)聯(lián)更新的觸摸與原始觸摸

  • @property(nonatomic,readonly) UITouchProperties estimatedProperties NS_AVAILABLE_IOS(9_1);:當(dāng)前觸摸對(duì)象估計(jì)的觸摸特性

  • @property(nonatomic,readonly) UITouchProperties estimatedPropertiesExpectingUpdates NS_AVAILABLE_IOS(9_1);:一組期望將來(lái)有傳入更新的屬性。如果估計(jì)屬性沒(méi)有更新,則當(dāng)前值是我們的最終估計(jì)值

四、關(guān)于UIEvent類

UIEvent是描述用戶與應(yīng)用程序交互的對(duì)象??梢砸暈橐粋€(gè)或者多個(gè)UITouch對(duì)象進(jìn)行動(dòng)作的過(guò)程。

  • 枚舉類型 -- UIEventType:
typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches,                           // 觸摸事件
    UIEventTypeMotion,                            // 運(yùn)動(dòng)事件
    UIEventTypeRemoteControl,                     // 遠(yuǎn)程控制事件
    UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0) // 深按事件
};
  • 枚舉類型 -- UIEventSubtype:上面 PS_Subtype 部分已經(jīng)做了解釋這里不多贅述。

  • @property(nonatomic,readonly) UIEventType type:事件類型

  • @property(nonatomic,readonly) UIEventSubtype subtype:事件類型的子類型

  • @property(nonatomic,readonly) NSTimeInterval timestamp;:事件發(fā)生的時(shí)間(自系統(tǒng)啟動(dòng)以來(lái)已經(jīng)過(guò)去的秒數(shù))

  • @property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches:返回與事件關(guān)聯(lián)的所有觸摸

  • - (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;:返回事件所屬的指定窗口的所有觸摸對(duì)象

  • - (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;:返回事件所屬的指定視圖的所有觸摸對(duì)象

  • - (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture:返回正在傳遞給指定的手勢(shì)識(shí)別器的觸摸對(duì)象

  • - (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch:返回與指定主要觸摸相關(guān)聯(lián)的由于在屏幕上滑動(dòng)太快而丟失的需要合并的所有觸摸。因?yàn)橛行┢聊粠倏赡軙?huì)比較低,當(dāng)你使用一款繪圖軟件時(shí)快速畫一個(gè)圓,那么呈現(xiàn)出來(lái)的可能會(huì)是一個(gè)看起來(lái)像是不規(guī)則多邊形的東西,這就是因?yàn)閬G失了一些輔助觸摸事件的原因,這一屬性可以提高觸摸精度。

  • - (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch:為指定觸摸將要發(fā)生的軌跡而預(yù)測(cè)的觸摸數(shù)組。最大限度的減少用戶的觸摸輸入和屏幕內(nè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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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