iOS中的事件

在iOS中不是所有對象都能處理事件,只有繼承了UIResponder的對象才能處理事件,我們稱之為"響應(yīng)者對象"

事件分類

  • 觸摸事件
  • 加速計(jì)事件
  • 遠(yuǎn)程控制事件

觸摸事件

// 系統(tǒng)自動調(diào)用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 該方法會持續(xù)調(diào)用
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 手指離開屏幕時調(diào)用
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
// 事件中斷時時調(diào)用
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);

加速計(jì)事件

- (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);

遠(yuǎn)程控制事件

- (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(4_0);

UITouch

  • 一個手指對應(yīng)一個UITouch對象
  • UITouch的作用
  1. 保存跟手指相關(guān)的信心,比如觸摸的位置,事件,階段
  2. 當(dāng)手指移動時,系統(tǒng)會一直更新該UITouch對象,使之能夠一直保存該手指的觸摸位置
  3. 當(dāng)手指離開屏幕時,系統(tǒng)會自動銷毀該UITouch對象
  • 獲取手指觸摸位置
UITouch *touch = [touches anyObject];
// 當(dāng)前觸摸的點(diǎn)
CGPoint currentP = [touch locationInView:self];
// 上一個觸摸的點(diǎn)
CGPoint previousP = [touch previousLocationInView:self];

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

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

事件傳遞的完整過程

  • 先將事件對象由上往下傳遞,找到最合適的控件來處理這個事件
  • 調(diào)用最合適控件的touches方法
  • 如果調(diào)用了[super touche..]方法,就會將事件順著響應(yīng)者鏈條向上傳遞,傳遞給上一個響應(yīng)者
  1. 先去判斷當(dāng)前的view是不是控制器的view,如果是,那么它的上一個響應(yīng)者就是它的控制器
  2. 如果當(dāng)前的view不是控制器的view,那么它的上一個響應(yīng)者就是它的父控件
  • 接著會調(diào)用上一個響應(yīng)者的touches方法

控件不能處理事件的原因

  • 如果父控件不能處理事件,那么它的子控件也不能接收處理事件
  • userInteractionEnabled = NO // 不接收用戶交互
  • hidden = YES (當(dāng)一個控件隱藏的時候,它的子控件也會跟隨父控件一起隱藏)
  • alpha = 0.0~0.01 (當(dāng)一個控件透明的時候,它的子控件也會跟隨父控件一起透明)

如何找到最適合的控件來處理事件

  • 自己是否能接收觸摸事件
  • 觸摸點(diǎn)是否在自己身上
  • 從后往前遍歷子控件,重復(fù)以上兩個步驟
  • 如果沒有符合條件的子控件,那么自己是最合適的

// 作用:去尋找最合適的View
// 什么時候調(diào)用:當(dāng)一個事件傳遞給當(dāng)前view就會調(diào)用該方法
// 返回的是誰,誰就是最適合的view
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    return nil;
}

hitTest方法的底層實(shí)現(xiàn)

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // 判斷自己能否處理觸摸事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {
        return nil;
    }
    
    // 判斷點(diǎn)是否在自己身上
    if (![self pointInside:point withEvent:event]) {
        return nil;
    }
    
    // 從后往前遍歷子控件,重復(fù)前兩步操作
    NSInteger count = self.subviews.count;
    for (NSInteger i = count -1; i >= 0; i--) {
        // 取出每一個view
        UIView *childView = self.subviews[i];
        // 轉(zhuǎn)換坐標(biāo)系
        CGPoint childP = [self convertPoint:point toView:childView];
        UIView *fitView = [childView hitTest:childP withEvent:event];
        
        // 判斷是否找到合適的view
        if (fitView) {
            return fitView;
        }
    }
    
    // 否則自己就是最合適的view
    return self;
}
// 判斷當(dāng)前的點(diǎn)在不在調(diào)用它的view上
// 調(diào)用時間: 在hitTest方法中調(diào)用
// point點(diǎn)必須要跟它調(diào)用者在同一個坐標(biāo)系里面
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    return YES;
}

UIGestureRecognizer手勢識別

  • UIGestureRecognizer它是一個抽象類
  • UITapGestureRecognizer(敲擊)
  • UIPinchGestureRecognizer(捏合)
// 獲取縮放比例
CGFloat scale = tap.scale;
// 復(fù)位操作
[pinch setScale:1];
  • UISwipeGestureRecognizer(輕掃)
  • 分方向direction
UISwipeGestureRecognizerDirectionRight
UISwipeGestureRecognizerDirectionLeft
UISwipeGestureRecognizerDirectionUp  
UISwipeGestureRecognizerDirectionDown
  • UIPanGestureRecognizer(拖拽)
// 相對于最原始的偏移量
CGPoint point = [pan translationInView:view];
// 復(fù)位操作
[pan setTranslation:CGPointZero inView:view];
  • UILongPressGestureRecognizer(長按)
  • 長按移動時,會持續(xù)調(diào)用目標(biāo)方法
  • 長按手勢分狀態(tài):state
 UIGestureRecognizerStatePossible
 UIGestureRecognizerStateBegan
 UIGestureRecognizerStateChanged
 UIGestureRecognizerStateEnded
 UIGestureRecognizerStateCancelled
 UIGestureRecognizerStateFailed
 UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
  • UIRotationGestureRecognizer(旋轉(zhuǎn))
// 獲取縮放角度
CGFloat rotation = tap.rotation;
// 復(fù)位操作
[tap setRotation:0];
  • 多個手勢操作
// 該代理方法用來判斷是否同時支持多個手勢操作
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

添加手勢方法

UIView *view = [[UIView alloc] init];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
// 設(shè)置代理
tap.delegate = self;
[view addGestureRecognizer:tap];

// 該代理方法可以用來設(shè)置可以點(diǎn)擊的區(qū)域
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    
    return YES;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赶诊,更是在濱河造成了極大的恐慌智哀,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幔摸,死亡現(xiàn)場離奇詭異拒迅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)卸察,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門脯厨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坑质,你說我怎么就攤上這事合武。” “怎么了涡扼?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵稼跳,是天一觀的道長。 經(jīng)常有香客問我吃沪,道長岂贩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任巷波,我火速辦了婚禮萎津,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抹镊。我一直安慰自己锉屈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布垮耳。 她就那樣靜靜地躺著颈渊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪终佛。 梳的紋絲不亂的頭發(fā)上俊嗽,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機(jī)與錄音铃彰,去河邊找鬼绍豁。 笑死,一個胖子當(dāng)著我的面吹牛牙捉,可吹牛的內(nèi)容都是我干的竹揍。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼邪铲,長吁一口氣:“原來是場噩夢啊……” “哼芬位!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起带到,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤昧碉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體被饿,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡四康,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锹漱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡慕嚷,死狀恐怖哥牍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喝检,我是刑警寧澤嗅辣,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站挠说,受9級特大地震影響澡谭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜损俭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一蛙奖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杆兵,春花似錦雁仲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至日裙,卻和暖如春吹艇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昂拂。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工受神, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人格侯。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓路克,卻偏偏與公主長得像,于是被迫代替她去往敵國和親养交。 傳聞我的和親對象是個殘疾皇子精算,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361

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

  • 好奇觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的?困惑于Cell怎么突然不能點(diǎn)擊了碎连?糾結(jié)于如何實(shí)現(xiàn)這個奇葩響應(yīng)需求灰羽?亦或是...
    Lotheve閱讀 57,358評論 51 599
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章廉嚼,感覺總結(jié)的已經(jīng)很到位玫镐,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,026評論 4 26
  • 01-UIView的拖拽 1.ios當(dāng)中常用的事件分為三種: 1.觸摸事件2.加速計(jì)事件3.遠(yuǎn)程控制事件 2.什么...
    freemanIT閱讀 397評論 0 0
  • -- iOS事件全面解析 概覽 iPhone的成功很大一部分得益于它多點(diǎn)觸摸的強(qiáng)大功能憋槐,喬布斯讓人們認(rèn)識到手機(jī)其實(shí)...
    翹楚iOS9閱讀 2,966評論 0 13
  • 響應(yīng)者對象 在iOS中不是任何對象都能處理事件双藕,只有繼承了UIResponder的對象才能接收并處理事件。我們稱之...
    JonesCxy閱讀 702評論 0 0