一、概述:
在iOS中事件一般分為三類(lèi)在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中并不是所有的類(lèi)都能處理接收并事件堪置,只有繼承自UIResponder
類(lèi)的對(duì)象才能處理事件,要處理特定類(lèi)型的事件张惹,響應(yīng)者必須覆蓋相應(yīng)的方法舀锨,UIResponder是用于響應(yīng)和處理事件的抽象界面。關(guān)于UIResponder類(lèi)的繼承關(guān)系如下所示:
二、關(guān)于UIResponder類(lèi)
1拧额、基礎(chǔ)屬性和方法:
-
nextResponder
:返回響應(yīng)者鏈中的下一個(gè)響應(yīng)者碑诉,如果沒(méi)有下一個(gè)響應(yīng)者返回nil。 -
- (BOOL)canBecomeFirstResponder
:返回一個(gè)布爾值侥锦,能否成為第一響應(yīng)者进栽,默認(rèn)是NO。子類(lèi)必須重寫(xiě)此方法并返回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
雀监。可以檢查evevt參數(shù)中subtype
屬性(UIEventSubtype結(jié)構(gòu)體類(lèi)型)以確定預(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類(lèi)
當(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ì)銷(xiāo)毀相應(yīng)的UITouch對(duì)象截亦。
1爬泥、UITouch的四個(gè)枚舉類(lèi):
(1)、觸摸階段判斷類(lèi):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è)類(lèi):UIForceTouchCapability
typedef NS_ENUM(NSInteger, UIForceTouchCapability) {
UIForceTouchCapabilityUnknown = 0, // 檢測(cè)失敗
UIForceTouchCapabilityUnavailable = 1, // 3D Touch不可用
UIForceTouchCapabilityAvailable = 2 // 3D Touch可用
};
(3)、觸摸接觸類(lèi)型類(lèi):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);
:觸摸類(lèi)型@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);
:返回在視圖中觸控筆的方位角莲绰。 僅適用于觸筆類(lèi)型欺旧。 參數(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);
:指向方位角方向的單位矢量戳晌。 僅適用于觸筆類(lèi)型鲫尊。傳遞視圖參數(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類(lèi)
UIEvent是描述用戶與應(yīng)用程序交互的對(duì)象扔字∧壹危可以視為一個(gè)或者多個(gè)UITouch對(duì)象進(jìn)行動(dòng)作的過(guò)程温技。
- 枚舉類(lèi)型 -- UIEventType:
typedef NS_ENUM(NSInteger, UIEventType) {
UIEventTypeTouches, // 觸摸事件
UIEventTypeMotion, // 運(yùn)動(dòng)事件
UIEventTypeRemoteControl, // 遠(yuǎn)程控制事件
UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0) // 深按事件
};
枚舉類(lèi)型 -- UIEventSubtype:上面 PS_Subtype 部分已經(jīng)做了解釋這里不多贅述。
@property(nonatomic,readonly) UIEventType type
:事件類(lèi)型@property(nonatomic,readonly) UIEventSubtype subtype
:事件類(lèi)型的子類(lèi)型@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í)快速畫(huà)一個(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)容渲染之間的延遲。