前言:我们知道,当发生点击事件时,系统通过
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
查找第一响应者。找到之后触发该响应者的UIResponder中的touch方法。
- 以下分析系统如何实现的,这是demo
- 首先我们观察系统的打印结果,在
- (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:]