事件傳遞和響應(yīng)過程

什么是事件傳遞

事件傳遞:在iOS系統(tǒng)中,事件可以分為三類:

public enum EventType : Int {

        
        case touches // 觸摸事件

        case motion // 運(yùn)動事件(比如重力感應(yīng)、搖一搖等等)

        case remoteControl // 遠(yuǎn)程控制事件(比如可以用耳機(jī)控制手機(jī))

        @available(iOS 9.0, *)
        case presses 
    }

touch events 大多數(shù)都是相同的,并且在觸摸事件發(fā)生的時(shí)候會傳遞給view;
motion events 由UIKit觸發(fā),并且會由Core Motion framework區(qū)分motion events;
Rmote-control events 允許響應(yīng)對象接收來自 external accessory 或者 headset 的命令,這樣就可以管理音頻和視頻了;
Press events 表示 a game controller 和 AppleTV 或者 其他有物理按鍵的設(shè)備的遠(yuǎn)程事件之間的交互

事件的傳遞過程:主要針對的是touch events

當(dāng)我們觸摸屏幕的時(shí)候,為我們找到最合適的view。
每當(dāng)手機(jī)觸摸屏幕,操作系統(tǒng)會把事件傳遞給當(dāng)前的APP,在UIApplication接收到手指的事件之后,就會去調(diào)用 UIWindow 的 hitTest:withEvent: 方法,看看當(dāng)前點(diǎn)擊的點(diǎn)是不是在window內(nèi),如果是則繼續(xù)調(diào)用其subview的 hitTest:withEvent: 方法,直到找到最后需要的view。

hitTest:withEvent: 的內(nèi)部實(shí)現(xiàn)

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.hidden || self.userInteractionEnabled == NO || self.alpha < 0.01 || [self pointInside:point withEvent:event]) {
        return nil;
    }
    for (UIView *subView in self.subviews.reverseObjectEnumerator) {
        UIView *hitView = [subView hitTest:[subView convertPoint:point fromView:self] withEvent:event];
        if (hitView) {
            return hitView;
        }
    }
    return self;
}

什么是響應(yīng)過程

在事件傳遞過程中,找到事件響應(yīng)的view,控件調(diào)用 touch 的一系列方法,判斷是否實(shí)現(xiàn) touch 的一系列方法,如果沒有實(shí)現(xiàn),就將事件傳遞給上一個(gè)響應(yīng)者,如果最終找不到,方法作廢

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

如果有實(shí)現(xiàn)就由此View來響應(yīng),如果沒有實(shí)現(xiàn),那么就傳遞給他的下一個(gè)響應(yīng)者。

我的理解:


在開發(fā)中的應(yīng)用

1.攔截點(diǎn)擊事件

重寫父視圖的 hitTest:withEvent: 方法

2.擴(kuò)大點(diǎn)擊面積

// 方法一
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    CGRect rect = self.bounds;
    rect = CGRectInset(rect, -30, -30); // 增加點(diǎn)擊面積
    return CGRectContainsPoint(rect, point);
}

// 方法二
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    CGRect rect = self.bounds;
    rect = CGRectInset(rect, -30, -30); // 增加點(diǎn)擊面積
    if (CGRectContainsPoint(rect, point)) {
        return self;
    }
    return nil;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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