hitTest(_:with:) とは
タップした位置からどのUIView がタップされたかを判断するUIViewのメソッドです。
オプショナルなUIView を返却します。
以下Apple の公式ドキュメントより。
Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.
https://developer.apple.com/documentation/uikit/uiview/1622469-hittest
指定されたポイントを含むビュー階層(それ自体を含む)内のレシーバーの最も遠い子孫を返します。(拙訳)
文章だけだとイメージしづらいと思うので図で示します。
基本的な処理の流れ
図にすると以下のイメージです。
UIView1 -> UIView2 -> UIView3 の順にaddSubView されていて、
オレンジの枠内をタップしたときの図。

hitTest メソッドは内部で以下のような再帰処理を行っています。
- タップ位置はUIView1 の枠内である
- タップ位置はUIView1 のsubview であるUIView2 の枠内である
- タップ位置はUIView2 のsubview であるUIView3 の枠内である
- UIView3 の subview はない
そして返り値として、最後に枠内だと判定したUIView3 を返却します。
結果、iOSはUIView3 がタップされたと判断されます。
基本的な考えはこんな感じです!
イメージしやすかったでしょうか🤔
例はめちゃくちゃシンプルな状況でしたが、
もう少し複雑な場合については Qiita: [iOS] hitTest(:with:)を具体例で解説する が分かりやすいかと思います!
勝手ながら補足すると、こちらで言及されている point(inside:with:) はUIView のメソッドで、
タップされたポイントがUIView の領域内に含まれているかをBool で返却します。
iOSのデフォルトの実装では推測ですが、hitTest 内の処理で
タップ位置が枠内かどうかを判定するときに呼び出していると思われます。
最後に
見た目の重なりがシンプルな親子関係通りであれば分かりやすいと思います。
ですが、例えばCollectionViewCell の領域からUIView がはみ出し、それが他のセルに被さっている場合は
もう少し考えることが増えそうです🤔
そのパターンについては、実践する機会があったので次回以降まとめようと思います。
今回は以上です!お疲れ様でした!
「[iOS] hitTest(_:with:) の挙動の概要」への1件のフィードバック