ios事件分發(fā)機制

image.png
官方文檔,摘取一部分說明:

“當(dāng)用戶 與 iPhone的觸摸屏產(chǎn)生互動時,硬件就會探測到物理接觸并且通知操作系統(tǒng)。接著操作系統(tǒng)就會創(chuàng)建相應(yīng)的事件并且將其傳遞給 當(dāng)前正在運行的應(yīng)用程序的事件隊列。然后 這項事件會被事件循環(huán)傳遞給優(yōu)先響應(yīng)者物件。優(yōu)先響應(yīng)者物件 是 事件 被觸發(fā)時 和 用戶 交互的物件,比如 按鈕物件、視圖物件。如果 我們 編寫了 代碼 讓 優(yōu)先響應(yīng)者 處理 這種類型的事件,那么 它 就會處理 這種類型的事件。處理完 某項事件后,響應(yīng)者 有 兩個選項:1、將 其 丟棄;2、將 其 傳遞給 響應(yīng)鏈條中的下一個響應(yīng)者。下一個響應(yīng)者的地址 存儲 在當(dāng)前響應(yīng)者物件所包含的變量nextResponder當(dāng)中。如果 優(yōu)先響應(yīng)者 無法處理 一項事件,那么 這項事件 就傳遞給 下一個響應(yīng)者,直到 這項事件 到達 能處理它的響應(yīng)者 或者 到達 響應(yīng)鏈條的末端,也就是 UIApplication類型的物件。UIApplication類型的物件 收到 一項事件后,也是要么處理要么丟棄?!?/p>

分發(fā)機制分兩步:

1: 事件傳遞鏈: 從上往下
2: 事件響應(yīng)鏈: 從下往上

hitTest 的順序如下
UIApplication -> UIWindow -> Root View -> ··· -> subview

事件響應(yīng)順序:可以通過nextResponder來獲取下一個響應(yīng)responder,優(yōu)先響應(yīng)view綁定的vc
Initial View -> View Controller(如果存在) -> superview -> · ·· -> rootView -> UIWindow -> UIApplication

image.png

主要用到的方法

1、尋找hitTestView(即最適合響應(yīng)這個事件的view),用到兩個方法

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

2、響應(yīng)時主要用到UIResponder里定義的方法,注意:只有找到真正的hitTestView,才會走事件響應(yīng)鏈,調(diào)用下面的響應(yīng)方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

重點:復(fù)現(xiàn)hitTest方法源碼,可以看出是如何找到hittestview的:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    if ([self pointInside:point withEvent:event]) {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subview convertPoint:point fromView:self];
            UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
    }
    return nil;
}

hitTest:withEvent:方法可能會被系統(tǒng)調(diào)用多次(蘋果開發(fā)者解釋為:系統(tǒng)可能會調(diào)整touch point,所以會多次調(diào)用hit test---https://lists.apple.com/archives/cocoa-dev/2014/Feb/msg00118.html

響應(yīng)鏈

//找離得最近的vc
- (UIViewController *)vc{
    id next = [self nextResponder];
    while(![next isKindOfClass:[ViewController class]]){
        return next;
    }
    return nil;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 這里可以做子view自己想做的事,做完后,事件繼續(xù)上傳,就可以讓其父類,甚至父viewcontroller獲取到這個事件了
[[selfnextResponder]touchesBegan:toucheswithEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[[selfnextResponder]touchesEnded:toucheswithEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[[selfnextResponder] touchesCancelled:toucheswithEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[[selfnextResponder] touchesMoved:toucheswithEvent:event];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 重點參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,701評論 0 15
  • iOS事件的傳遞與響應(yīng)是一個重要的話題,網(wǎng)上談?wù)摰暮芏啵蠖嘀v述并不完整,本文將結(jié)合蘋果官方的文檔對事件的傳遞與...
    還是不夠辣閱讀 4,660評論 4 31
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,250評論 4 26
  • 本文主要講解iOS觸摸事件的一系列機制,涉及的問題大致包括: 觸摸事件由觸屏生成后如何傳遞到當(dāng)前應(yīng)用? 應(yīng)用接收觸...
    baihualinxin閱讀 1,279評論 0 9
  • 當(dāng)你手指觸摸屏幕后會發(fā)生以下事情:觸摸事件被封裝成一個UIEvent事件,去當(dāng)前iOS操作系統(tǒng)的active...
    傲世情緣閱讀 1,039評論 0 4

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