熟記響應(yīng)者鏈沒大毛用,主要還是要從代碼層面去理解其過程。從圖記起:

MJ圖

點(diǎn)擊E為例
以點(diǎn)擊E為例Hittest步驟如下:
1.觸摸點(diǎn)在ViewA內(nèi),所以檢查SubViewB.C
2.觸摸點(diǎn)不在ViewB內(nèi),所以檢查ViewC的Subviews
3.觸摸點(diǎn)不在ViewD內(nèi),發(fā)生在ViewE內(nèi),所以hitTest最終返回ViewE;
PS: 子控件超出父視圖之外的部分點(diǎn)擊無效也正是基于此
//hitTest內(nèi)部通過pointInside:withEvent:方法來確定觸摸點(diǎn)是否在視圖內(nèi)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//透明或隱藏或關(guān)閉交互,則返回nil
if (self.alpha <= 0.01 || !self.userInteractionEnabled || self.hidden) {
return nil;
}
BOOL inside = [self pointInside:point withEvent:event];
//觸摸點(diǎn)在當(dāng)前視視圖
if (inside) {
//逆向遍歷子視圖
NSEnumerator *enumerator = [self.subviews reverseObjectEnumerator];
for (UIView *subview in enumerator) {
UIView *hitView = [subview hitTest:point withEvent:event];
if (hitView) {
break;
}
}
if (!hitView) {
hitView = self;
}
return hitView;
} else {
return nil;
}
}
最后附上一個(gè)穿透點(diǎn)擊事件
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *view = [super hitTest:point withEvent:event];
if ([view isEqual:self.btn1]) {
return self.btn0;
}
return view;
}