分析系统查找第一响应者的过程实现

前言:我们知道,当发生点击事件时,系统通过 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event查找第一响应者。找到之后触发该响应者的UIResponder中的touch方法。

  • 以下分析系统如何实现的,这是demo
分析系统查找第一响应者的过程实现_第1张图片
数字对应的是该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 ->>
 hit end 102 ->>
 hit end 100 ->>
 hit start -- >100
 hit start -- >101
 hit end 101 ->(null)
 hit start -- >102
 hit start -- >104
 hit end 104 ->>
 hit end 102 ->>
 hit end 100 ->>
 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 ->>
  hit end 102 ->>
  hit end 100 ->>
  hit start -- >100
  hit start -- >101
  hit end 101 ->(null)
  hit start -- >102
  hit start -- >104
  hit end 104 ->>
  hit end 102 ->>
  hit end 100 ->>
  104 ->-[TestView touchesBegan:withEvent:]

是不是差不多?

你可能感兴趣的:(分析系统查找第一响应者的过程实现)