iOS 事件傳遞與視圖響應(yīng)鏈

當(dāng)你點擊了屏幕上的某個view,這個動作由硬件層傳導(dǎo)到操作系統(tǒng),UIKit 就會打包出一個 UIEvent 對象,然后會把這個Event分發(fā)給當(dāng)前正在活躍的 App ,告知當(dāng)前活動的App有事件之后,UIApplication 單例就會從事件隊列中去取最新的事件,然后分發(fā)給能夠處理該事件的對象。UIApplication 獲取到Event之后,Application就糾結(jié)于到底要把這個事件傳遞給那個View來響應(yīng)這個事件,這時候就要依靠HitTest來決定了。

iOS中,Hit-Test的作用就是找出這個觸摸點下面的View是什么,HitTest會檢測這個點擊的點是不是發(fā)生在這個View上,如果是的話,就會去遍歷這個View的subviews,直到找到最小的能夠處理事件的view,如果整了一圈沒找到能夠處理的view,則返回自身然后從sub View 又開始找。

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

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
image.png
邏輯流程圖
image.png
具體實現(xiàn)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // 1.判斷當(dāng)前控件能否接收事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {return nil;}
    
    // 2. 判斷點在不在當(dāng)前控件
    if ([self pointInside:point withEvent:event] == NO) {return nil;}

    // 3.從后往前遍歷自己的子控件
    NSInteger subViewCoutn = self.subviews.count;

    for (NSInteger i = subViewCoutn - 1; i >= 0; i--) {
        // 取subView
        UIView *childView = self.subviews[i];
        // 把當(dāng)前控件上的坐標(biāo)系轉(zhuǎn)換成子控件上的坐標(biāo)系
        CGPoint childP = [self convertPoint:point toView:childView];
        // 尋找到最合適的view
        UIView *fitView = [childView hitTest:childP withEvent:event];
        
        if (fitView) {
            return fitView;
        }
    }
    
    NSLog(@"點擊了:%@",NSStringFromClass([self class]));

    // 循環(huán)結(jié)束,表示沒有比自己更合適的view
    return self;
    
}
最后編輯于
?著作權(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ù)。

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