まず、コールスタックを見て、ヒットテストメソッドの実行ロジックを確認します。
上の2つの図に示されているように、hittestの呼び出しロジックは次のようになり、ウィンドウから開始して、このメソッドで再びhittestを呼び出します。
すべてのサブビューのhittestメソッドを呼び出すために、内部のポイントがhittestメソッドで呼び出されます。
クリックポイントが独自の範囲内にあるかどうかを判断し、独自の範囲内にある場合は、子コントロールのヒットテストメソッドを呼び出します
つまり、ビューがhittestメソッドを呼び出すかどうかは、クリックポイントがその親ビューのスコープ内にあるかどうかによって異なります。
原則:タッチポイントが自分自身にあるかどうかを確認し、最後に子コントロールを後ろから前にトラバースします。子コントロールをトラバースするときは、前の2つの手順をもう一度繰り返してから、親コントロールの座標点をの座標系に変換します。子コントロール。クリックしてもう一度hitTestメソッドを実行し、トラバースします。
主要な擬似コードは次のとおりです
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//系统默认会忽略isUserInteractionEnabled设置为NO、隐藏、或者alpha小于等于0.01的视图
if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
return nil;
}
if ([self pointInside:point withEvent:event]) {
for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
CGPoint convertedPoint = [subview convertPoint:point fromView:self];
UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
if (hitTestView) {
return hitTestView;
}
}
return self;
}
return nil;
}
コード検証
図のように、空白部分をクリックします
図に示すように、空のテーブルをクリックすると、ビューaのヒットテストが実行されますが、ビューbは実行されず、ビューaの親ビューは実行されます。
vcビュー、bビューの親ビューはaです。これは、クリックポイントがvcビュー(aの親ビュー)の範囲内にあるため、ビューの最もヒットしたメソッドが実行されるためです。
ただし、クリックポイントはビューa(bの親ビュー)の範囲内にないため、ビューbの最もヒットしたメソッドは実行されません。
さらに、hittestメソッドをアクティブに呼び出すことはできず、書き換えることしかできず、アクティブな呼び出しの返されたビューはすべて空であることがわかりました。
このメソッドはオーバーライドのみが可能で、呼び出すことはできません
しかし、内部のポイントは積極的に呼び出すことができます