iOS觸摸事件詳解

目錄:
1 UITouch
1.1 UITouch的創(chuàng)建
1.2 UITouch的作用
1.3 UITouch的常用屬性
1.4 UITouch的常用方法
2.UIEvent
3.UIResponder詳解
4.手勢UIGestureRecognizer
5.響應(yīng)鏈
6.iOS觸摸事件詳解
6.1 事件傳遞
6.2 事件轉(zhuǎn)發(fā)
6.3 事件響應(yīng)
7.Touch Event番官、UIGestureRecognizer、響應(yīng)鏈之間的關(guān)系
7.1 關(guān)聯(lián)詳解
7.2 攔截
總結(jié)

1. UITouch

1.1 UITouch的創(chuàng)建

當(dāng)用戶用一根手指觸摸屏幕時(shí)徘熔,會創(chuàng)建一個與手指相關(guān)聯(lián)的UITouch對象淆党,一根手指對應(yīng)一個UITouch對象酷师。

1.2 UITouch的作用

UITouch保存著跟手指相關(guān)的信息染乌,比如觸摸的位置、時(shí)間荷憋、階段等。
當(dāng)手指移動時(shí)勒庄,系統(tǒng)會更新同一個UITouch對象,使之能夠一直保存該手指在的觸摸位置实蔽。
當(dāng)手指離開屏幕時(shí),系統(tǒng)會銷毀相應(yīng)的UITouch對象坛吁。

1.3 UITouch的常用屬性
/// 觸摸產(chǎn)生時(shí)所處的窗口。由于窗口可能發(fā)生變化阶冈,當(dāng)前所在的窗口不一定是最開始的窗口
@property(nonatomic,readonly,retain) UIWindow *window;

/// 觸摸產(chǎn)生時(shí)所處的視圖。由于視圖可能發(fā)生變化女坑,當(dāng)前視圖也不一定時(shí)最初的視圖
@property(nonatomic,readonly,retain) UIView *view;

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

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

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

//Touch 狀態(tài)枚舉
typedef NS_ENUM(NSInteger, UITouchPhase) {
    UITouchPhaseBegan,             // whenever a finger touches the surface.
    UITouchPhaseMoved,             // whenever a finger moves on the surface.
    UITouchPhaseStationary,        // whenever a finger is touching the surface but hasn't moved since the previous event.
    UITouchPhaseEnded,             // whenever a finger leaves the surface.
    UITouchPhaseCancelled,         // whenever a touch doesn't end but we need to stop tracking (e.g. putting device to face)
};
1.4 UITouch的常用方法
- (CGPoint)locationInView:(UIView *)view;
//返回值表示觸摸在view上的位置
//這里返回的位置是針對view的坐標(biāo)系的(以view的左上角為原點(diǎn)(0, 0))
//調(diào)用時(shí)傳入的view參數(shù)為nil的話,返回的是觸摸點(diǎn)在UIWindow的位置

- (CGPoint)previousLocationInView:(UIView *)view;
//記錄了前一個觸摸點(diǎn)的位置

2.UIEvent官方文檔

1瓮钥、觸摸事件:第一個手指開始觸摸屏幕到最后一個手指離開屏幕定義為一個觸摸事件。

2碉熄、UIEvent實(shí)際包括了多個UITouch對象桨武。有幾個手指觸碰锈津,就會有幾個UITouch對象。

@interface UIEvent : NSObject
@property(nonatomic,readonly) UIEventType     type NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly) UIEventSubtype  subtype NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly) NSTimeInterval  timestamp;
#if UIKIT_DEFINE_AS_PROPERTIES

@property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches;
//省略部分代碼
@end
typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches, // 觸摸事件
    UIEventTypeMotion, // 加速計(jì)事件
    UIEventTypeRemoteControl, // 遠(yuǎn)程事件
    UIEventTypePresses , // 物理按壓事件
};

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,
    UIEventSubtypeRemoteControlNextTrack            = 104,
    UIEventSubtypeRemoteControlPreviousTrack        = 105,
    UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
    UIEventSubtypeRemoteControlEndSeekingBackward   = 107,
    UIEventSubtypeRemoteControlBeginSeekingForward  = 108,
    UIEventSubtypeRemoteControlEndSeekingForward    = 109,
};

UIEvent中包含若干UITouch性誉,當(dāng)某個UITouch對象的phase狀態(tài)發(fā)生變化,系統(tǒng)會產(chǎn)生一條TouchMessage错览,繼而傳遞和派發(fā)Touch message。
也就是說每次用戶手指的移動和變化倾哺,UITouch都會形成狀態(tài)改變,系統(tǒng)便會產(chǎn)生TouchMessage悼粮。一次觸摸事件是由一組UITouch對象狀態(tài)變化引起的一組Touch message的傳遞和轉(zhuǎn)發(fā)曾棕。

3 UIResponder詳解

3.1 UIResponder類可以接收并處理事件扣猫。

3.2 UIApplication翘地、AppDelegate、UIViewController衙耕、UIView均繼承UIResponder類。

3.3 UIResponder類的nextResponser橙喘。

Return value:UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t);UIViewController implements the method by returning its view’s superview; UIWindow returns the application object, and UIApplication returns nil.

1)UIView的nextResponder,如果存在管理的UIViewController對象厅瞎,返回UIViewController對象,如果沒有彭雾,返回父視圖;

2)UIViewController的nextResponder是self.view薯酝;

3)UIWindow的nextResponder是application對象半沽;

4)Application的nextResponder是nil吴菠;

@interface UIResponder : NSObject <UIResponderStandardEditActions>

//觸摸事件
- (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;
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);

//物理按鈕,遙控器上面的按鈕在按壓狀態(tài)等狀態(tài)下的回調(diào)
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);

//設(shè)備的陀螺儀和加速傳感器使用
- (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
- (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);

// 省略部分代碼
@end

4.手勢UIGestureRecognizer

為沒有繼承UIControl的視圖對象添加響應(yīng)事件

4.1 UIGestureRecognizer類包含UIResponder類中的以下方法:
- (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;
4.2 手勢狀態(tài)
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
    //未知狀態(tài)
    UIGestureRecognizerStatePossible,   // the recognizer has not yet recognized its gesture, but may be evaluating touch events. this is the default state
    //首次識別狀態(tài)橄务,對于連續(xù)手勢幔托,例如長按穴亏,有這種狀態(tài)
    UIGestureRecognizerStateBegan,      // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop
    //再次識別蜂挪,當(dāng)手連續(xù)手勢識別之后,再次受到touch事件
    UIGestureRecognizerStateChanged,    // the recognizer has received touches recognized as a change to the gesture. the action method will be called at the next turn of the run loop
    //識別完成嗓化,受到touchend 消息之后
    UIGestureRecognizerStateEnded,      // the recognizer has received touches recognized as the end of the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
    //取消識別
    UIGestureRecognizerStateCancelled,  // the recognizer has received touches resulting in the cancellation of the gesture. the action method will be called at the next turn of the run loop. the recognizer will be reset to UIGestureRecognizerStatePossible
    //識別失敗
    UIGestureRecognizerStateFailed,     // the recognizer has received a touch sequence that can not be recognized as the gesture. the action method will not be called and the recognizer will be reset to UIGestureRecognizerStatePossible
    // Discrete Gestures – gesture recognizers that recognize a discrete event but do not report changes (for example, a tap) do not transition through the Began and Changed states and can not fail or be cancelled
    //識別狀態(tài)棠涮,與識別結(jié)束一個意思
    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
};
image.png

結(jié)合圖我們來看手勢的整個遷移過程,先明確幾個信息

1)手勢的狀態(tài)遷移严肪,前提是收到Touch message,才能做狀態(tài)變化處理代碼谦屑。
2)手勢分為連續(xù)狀態(tài)手勢驳糯、不連續(xù)狀態(tài)手勢吉执。連續(xù)手勢有長按恨溜,慢滑等逸嘀。不連續(xù)手勢有單擊胶坠,雙擊等等缆镣。
3)當(dāng)用戶沒有點(diǎn)擊屏幕证薇,所有手勢都處于Possiable初始狀態(tài)疾党。
當(dāng)用戶點(diǎn)擊屏幕间狂,手勢會收到Touch Began Message坦康, 手勢的touchBegan方法會被調(diào)用竣付,手勢開始記錄點(diǎn)擊位置和時(shí)間,仍處于 Possiable狀態(tài)滞欠。

如果用戶按住不放古胆,間隔超過一定時(shí)間,單擊手勢會變化為Failed狀態(tài)筛璧,并在下個一runloop變?yōu)閜ossiable逸绎。

如果時(shí)間大于長按手勢設(shè)定時(shí)間,長按手勢就會變化為Began狀態(tài)隧哮,當(dāng)用戶移動手指桶良,長按手勢的touch move方法被調(diào)用,長按手勢將自己狀態(tài)設(shè)置為Changed狀態(tài)沮翔,并且也會回調(diào)處理方法陨帆。最后手指離開曲秉,系統(tǒng)調(diào)用長按手勢touchEnd方法,手勢狀態(tài)設(shè)置為 Recognized狀態(tài)疲牵。

4.3 混合手勢處理

1)當(dāng)給UIView添加多個UIGestureRecognizer對象時(shí)承二,默認(rèn)只有1個生效。如果想全部都生效纲爸,讓協(xié)議中的gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法返回YES亥鸠。

2)同時(shí)添加單擊和雙擊,也均允許生效识啦。問題來了负蚊,那雙擊屏幕時(shí),默認(rèn)觸發(fā)1次單擊事件和1次雙擊事件颓哮。但這不是想要的效果家妆,如何實(shí)現(xiàn)雙擊時(shí),只觸發(fā)雙擊手勢呢冕茅,單擊時(shí)只觸發(fā)單擊手勢呢伤极?解決方案是讓協(xié)議中的gestureRecognizer:shouldRequireFailureOfGestureRecognizer:方法、

gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:方法都返回YES姨伤。

4.4 UIGestureRecognizerDelegate協(xié)議
@protocol UIGestureRecognizerDelegate <NSObject>
@optional

// 手勢狀態(tài)是否允許更改哨坪,默認(rèn)為YES。
// 如果實(shí)現(xiàn)中返回NO,那么手勢最后都為失敗狀態(tài)乍楚。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

// 允許多個手勢生效当编,默認(rèn)為NO。
// 如果實(shí)現(xiàn)中返回YES炊豪,同時(shí)添加單擊和雙擊手勢凌箕,雙擊屏幕時(shí),同時(shí)產(chǎn)生1次單擊事件和1次雙擊事件
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

// 以下2個方法词渤,為手勢之間添加依賴牵舱,默認(rèn)NO。
// 比如單擊和雙擊缺虐,如果雙擊手勢識別失敗芜壁,轉(zhuǎn)換為識別單擊手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

// 手勢是否關(guān)注UITouch、UIPress對象狀態(tài)變化高氮,和gestureRecognizerShouldBegin:效果類似慧妄,默認(rèn)為YES。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press;

@end
4.5 蘋果封裝以下幾個手勢

(1)UITapGestureRecognizer

單個或多個塞子剪芍。指定數(shù)量的手指必須要承認(rèn)的姿態(tài)塞淹,挖掘查看指定的次數(shù)。

(2)UIPinchGestureRecognizer

看起來捏的手勢罪裹,涉及兩個接觸饱普。當(dāng)用戶將兩個手指运挫,向?qū)Ψ降膫鹘y(tǒng)意義是縮小;當(dāng)用戶將兩個手指從彼此遠(yuǎn)離,傳統(tǒng)意義變焦套耕。

(3)UIRotationGestureRecognizer

看起來輪換涉及兩個觸摸手勢谁帕。當(dāng)用戶移動手指對面對方的圓周運(yùn)動,基本的觀點(diǎn)應(yīng)該在相應(yīng)的方向和速度旋轉(zhuǎn)冯袍。

(4)UISwipeGestureRecognizer

看起來刷卡在一個或多個方向的手勢匈挖。抨擊是一個獨(dú)立的姿態(tài),因此康愤,相關(guān)的操作的消息發(fā)送每個手勢只有一次儡循。

(5)UIPanGestureRecognizer

看起來平移(拖動)的手勢。用戶必須按查看上一個或更多的手指翘瓮,而他們平移贮折。實(shí)施這個手勢識別動作方法的客戶端可以要求它目前的翻譯和手勢的速度裤翩。

(6)UILongPressGestureRecognizer

看起來長按手勢资盅。用戶必須按下一個或更多的手指行動訊息傳送至少指定期限。此外踊赠,手指可能要承認(rèn)的姿態(tài)移動唯一指定的距離;如果他們超越這個限制的姿態(tài)失敗呵扛。

5. 響應(yīng)鏈

響應(yīng)鏈由UIResponder對象為node,形成的一個鏈表狀結(jié)構(gòu)筐带,通過UIResonder的nextResonder鏈接今穿。
下圖中節(jié)點(diǎn)關(guān)系是箭頭方向朝上,也就是subView指向superView伦籍。


image.png
image.png
image.png
image.png

6.iOS觸摸事件詳解

事件傳遞是在響應(yīng)鏈中查找hitTestView的過程蓝晒,從父View到子View。事件轉(zhuǎn)發(fā)是響應(yīng)消息中觸發(fā)的帖鸦,從子View通過nextResponder在響應(yīng)鏈中回溯芝薇。

6.1 事件傳遞

1)找到設(shè)備中的Application。

觸摸屏幕時(shí)作儿,由iOS系統(tǒng)的硬件進(jìn)程獲取洛二,簡單封裝事件后暫存在系統(tǒng)中,利用端口實(shí)現(xiàn)與Application進(jìn)程完成通信攻锰,將事件傳遞給Application進(jìn)程晾嘶。

當(dāng)應(yīng)用程序啟動時(shí),主線程的RunLoop會注冊一個基于端口的source娶吞,當(dāng)接收到相關(guān)事件時(shí)垒迂,主線程會被喚醒執(zhí)行觸摸事件。

2)通過響應(yīng)鏈找到最終處理事件的hitTestView妒蛇。

當(dāng)Application接收到新的事件時(shí)机断,開始尋找響應(yīng)鏈中的hitTestView策添。

將所有的顯示在屏幕上的 "UIWindow對象",按照層級結(jié)構(gòu)從上到下排列成一個數(shù)組毫缆。從第一個UIWindow對象開始唯竹,先判斷UIWindow是否不隱藏且可見度大于0.01且可交互,再判斷點(diǎn)擊位置在不在這個UIWindow內(nèi)苦丁。

如果不在 浸颓,返回nil, 就換下一個UIWindow;

如果在的話旺拉,并且UIWindow沒有subView就返回自己产上,但如果UIWindow有subViews,就遞歸遍歷整個subViews蛾狗,直到找到hitTestView晋涣。

如果沒有找到到就不做傳遞。

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event {
  //判斷該視圖是否滿足響應(yīng)事件的條件
    if (!self.hidden && self.alpha > 0.01 && self.isUserInteractionEnabled) {
        //判斷點(diǎn)擊位置是否在自己區(qū)域內(nèi)部
        if ([self pointInside: point withEvent:event]) {
            UIView *attachedView;
            // 遍歷子視圖
            for (int i = self.subviews.count - 1; i >= 0; i--) {
                UIView *view  = self.subviews[i];
                // 對子view遞歸調(diào)用本方法
                attachedView =  [view hitTest:point withEvent:event];
                if (attachedView)
                    break;
            }
            if (attachedView)  {
                return attachedView;
            } else {
                return self;
            }
        }
    }
    return nil;
}
6.2 事件轉(zhuǎn)發(fā)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    //do someThiing
  [self.nextResponser touchesBegan: touches withEvent:event];
}
6.3 事件響應(yīng)

當(dāng)鎖定hitTestView后沉桌,當(dāng)觸摸狀態(tài)發(fā)生變化谢鹊,會不停的收到UITouch Message消息,調(diào)用hitTestView從UIResponder類繼承的方法留凭。

// 點(diǎn)擊剛開始佃扼,回調(diào)這個方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 點(diǎn)擊之后移動,回調(diào)這個方法
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 手指移開蔼夜、點(diǎn)擊結(jié)束兼耀,回調(diào)這個方法
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 事件被手勢識別,回調(diào)這個方法
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

7.Touch Event求冷、UIGestureRecognizer瘤运、響應(yīng)鏈之間的關(guān)系

image.png
7.1 關(guān)聯(lián)詳解

第一步:系統(tǒng)會將所有的Touch message優(yōu)先發(fā)送給關(guān)聯(lián)在響應(yīng)鏈上的全部手勢。手勢根據(jù)Touch序列消息和手勢基本規(guī)則更改自己的狀態(tài)(有的可能失敗匠题,有的可能識別等等)拯坟。如果某個手勢對Touch message成功攔截(被攔截時(shí),系統(tǒng)不會將Touch message 發(fā)送給響應(yīng)鏈頂部響應(yīng)者)梧躺,頂部視圖控件調(diào)用touchesCancelled:withEvent方法似谁,否則系統(tǒng)會進(jìn)入第二步。

第二步:系統(tǒng)將Touch message發(fā)送給響應(yīng)鏈頂部的視圖控件掠哥,頂部視圖控件這個時(shí)候就會調(diào)用Touch相關(guān)的四個方法中的某一個巩踏。

7.2 攔截

舉例說明:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleClick)];
    gesture.numberOfTapsRequired = 2;
    self.view.userInteractionEnabled = YES;

    [self.view addGestureRecognizer:gesture];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesBegan");
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesEnded");
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesMoved");
}

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesCancelled");
}

- (void)doubleClick {
    NSLog(@"雙擊拉");
}

結(jié)果分析:
1)如果單擊屏幕(攔截失敗),打印
TestForMoreGesture[26097:18114462] touchesBegan
TestForMoreGesture[26097:18114462] touchesEnded
2)如果雙擊屏幕(攔截成功)续搀,打印
TestForMoreGesture[26097:18114462] touchesBegan
TestForMoreGesture[26097:18114462] 雙擊拉
TestForMoreGesture[26097:18114462] touchesCancelled

手勢是否攔截該Touch Message,主要由UIGestureRecognizer類的三個屬性控制塞琼。

// 默認(rèn)為YES,表明當(dāng)手勢成功識別事件后,系統(tǒng)會將Touch cancel消息發(fā)送給hitTestView 禁舷,并調(diào)用hitTestView的TouchCancel彪杉。設(shè)置為NO毅往,不會再收到TouchCancel
@property(nonatomic) BOOL cancelsTouchesInView;
// 默認(rèn)為YES, 表明無論什么情況下,不會攔截Touch began消息派近。如果設(shè)置為NO攀唯,只要有一個手勢不識別失敗,都不會發(fā)送Touch began到響應(yīng)鏈的第一響應(yīng)者渴丸。
@property(nonatomic) BOOL delaysTouchesBegan; 
// 默認(rèn)為NO, 和delaysTouchesBegan類似侯嘀,不過它是用來控制TouchEnd message的攔截
@property(nonatomic) BOOL delaysTouchesEnded; 

總結(jié)

iOS整個事件處理的過程就是這樣,系統(tǒng)為完成整個交互做了很多東西谱轨,核心點(diǎn)如下:

1戒幔、事件分發(fā)過程分為:1.事件消息傳遞;2.事件消息分發(fā)土童。

2诗茎、響應(yīng)網(wǎng)是事件響應(yīng)的基礎(chǔ),響應(yīng)鏈?zhǔn)鞘录憫?yīng)的具體路徑献汗。

3敢订、事件消息分發(fā)優(yōu)先發(fā)送給手勢集合,手勢內(nèi)部會做沖突處理雀瓢,過濾消息枢析。不被過濾的消息會傳遞給響應(yīng)鏈對象。

參考文章:
iOS觸摸事件詳解
深入淺出iOS事件機(jī)制

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刃麸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子司浪,更是在濱河造成了極大的恐慌泊业,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啊易,死亡現(xiàn)場離奇詭異吁伺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)租谈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門篮奄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人割去,你說我怎么就攤上這事窟却。” “怎么了呻逆?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵夸赫,是天一觀的道長。 經(jīng)常有香客問我咖城,道長茬腿,這世上最難降的妖魔是什么呼奢? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮切平,結(jié)果婚禮上握础,老公的妹妹穿的比我還像新娘。我一直安慰自己悴品,他們只是感情好弓候,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著他匪,像睡著了一般菇存。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上邦蜜,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天依鸥,我揣著相機(jī)與錄音,去河邊找鬼悼沈。 笑死贱迟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的絮供。 我是一名探鬼主播衣吠,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼壤靶!你這毒婦竟也來了缚俏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贮乳,失蹤者是張志新(化名)和其女友劉穎忧换,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體向拆,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亚茬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浓恳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刹缝。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖颈将,靈堂內(nèi)的尸體忽然破棺而出梢夯,到底是詐尸還是另有隱情,我是刑警寧澤吆鹤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布厨疙,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏沾凄。R本人自食惡果不足惜梗醇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撒蟀。 院中可真熱鬧叙谨,春花似錦、人聲如沸保屯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姑尺。三九已至竟终,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間切蟋,已是汗流浹背统捶。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柄粹,地道東北人喘鸟。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像驻右,于是被迫代替她去往敵國和親什黑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359