分析系統查詢第一響應者的過程實現

swcfsfy發表於2017-12-13

前言:我們知道,當發生點選事件時,系統通過 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event查詢第一響應者。找到之後觸發該響應者的UIResponder中的touch方法。

數字對應的是該View的tag,以下實現中均點選tag為104的View

  • 首先我們觀察系統的列印結果,在- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 中新增如下程式碼
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"hit start -- >%ld",self.tag);
    UIView *v = [super hitTest:point withEvent:event];
    NSLog(@"hit end %ld ->%@",self.tag,v);
    return v;
}
複製程式碼
  • 列印結果如下
 hit start -- >100
 hit start -- >101
 hit end 101 ->(null)
 hit start -- >102
 hit start -- >104
 hit end 104 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 hit end 102 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 hit end 100 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 hit start -- >100
 hit start -- >101
 hit end 101 ->(null)
 hit start -- >102
 hit start -- >104
 hit end 104 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 hit end 102 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 hit end 100 -><TestView: 0x7fb3a1f8ef80; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fb3a1f87190>>
 104 ->-[TestView touchesBegan:withEvent:]
複製程式碼
  • 以下是模仿系統實現的方法
- (UIView *)__adHitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (![self pointInside:point withEvent:event]) {
        return nil;
    }
    
    if (self.userInteractionEnabled == NO) {
        return nil;
    }
    
    if (self.alpha < 0.01) {
        return nil;
    }
    
    if (self.hidden == YES) {
        return nil;
    }
    
    if (self.subviews.count) {
        
        for (NSUInteger i = self.subviews.count; i > 0; i--) {
        
            UIView *sub = self.subviews[i-1];
            
            CGPoint p = [self convertPoint:point toView:sub];
            
            UIView *t = [sub hitTest:p withEvent:event];
            
            if (t != nil) {
                return t;
            }
        }
    }
    
    return self;
}
複製程式碼
  • - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event換成模仿的實現
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"hit start -- >%ld",self.tag);
    UIView *v = [self __adHitTest:point withEvent:event];
    NSLog(@"hit end %ld ->%@",self.tag,v);
    return v;
}
複製程式碼
  • 觀察模仿後的列印結果
hit start -- >100
  hit start -- >101
  hit end 101 ->(null)
  hit start -- >102
  hit start -- >104
  hit end 104 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  hit end 102 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  hit end 100 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  hit start -- >100
  hit start -- >101
  hit end 101 ->(null)
  hit start -- >102
  hit start -- >104
  hit end 104 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  hit end 102 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  hit end 100 -><TestView: 0x7fd22ac1d680; frame = (29 89; 176 61); autoresize = RM+BM; tag = 104; layer = <CALayer: 0x7fd22ac1d7f0>>
  104 ->-[TestView touchesBegan:withEvent:]
複製程式碼

###是不是差不多?

相關文章