前言:我們知道,當發生點選事件時,系統通過
- (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:]
複製程式碼
###是不是差不多?