게다가 아이폰에서는 적용되는데, 동작하지 않는 것이 아이패드 뿐이라면..!
hitTest(_:with:) | Apple Developer Documentation
Returns the farthest descendant in the view hierarchy of the current view, including itself, that contains the specified point.
developer.apple.com
디스플레이에 touch down 이벤트가 입력되면 터치된 뷰에서부터 가장 먼 뷰를 찾아서 반환하는 메서드이다.

func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.hidden
|| !self.userInteractionEnabled
|| self.alpha < 0.01
|| ![self pointInside:point withEvent:event]
|| ![self _isAnimatedUserInteractionEnabled] {
return nil
}
if /* point is in our bounds */ {
for /* each subview, in reverse order */ {
let hitView = /* recursive call on subview */
if hit view != nil {
return hitView
}
}
return self
}
return nil
}
수도로는 이렇게 구현되어 있다. 대충 뷰가 가진 프로퍼티에 대해 합리적인 조건을 검사한 다음 DFS 방식으로 뷰를 찾아서 반환한다.
hitTest에 대한 WWDC14 영상이 공홈에는 공개되어있지 않은 것 같은데 여기저기 찾아보면 영상 링크를 찾을 수 있다고 한다. (공유받아서 링크가 없다...!) 대신 wwdc note 도큐먼트는 여기 🔗
Documentation
wwdcnotes.com
팀에서는 특정 뷰가 hit되지 않도록 이 메서드를 오버라이드해 사용하는데, 내가 하려던 것은 아래의 그림과 같이 A 윈도우 위에 B를 배치하는 상황에서 B가 아닌 영역의 인터랙션은 A에서 동작하는 것이다.


override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
if hitView == self {
return nil
}
return hitView
}
이렇게 오버라이드해서 갖다쓰면 아이폰에서는 아주 잘 동작하지만 아이패드에서는 B's UIWindow만 인터랙티브했다 .. A는 어디를 눌러도 전혀 반응이 없었다. 디버깅을 하루종일 하고서야 무슨 차이가 있는지 알 수 있었는데


아이패드는 뷰 hierarchy에 UIView 하나가 껴있다. hitTest에서 윈도우가 아닌 이 UIView를 자꾸 반환해서 제대로 적용이 안되었던 것이다. 해결한 방법은 히트된 영역이 window(포함)와 viewController 사이에 포함되어 있는지를 반환하도록 수정했다. 사진에서 빨간 영역에 포함되는지를 반환하는 것이다.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
if hitView == self {
return nil
}
guard let hitView, let rootViewController else { return hitView }
if self.contains(hitView) && !rootViewController.contains(hitView) {
return nil
}
return hitView
}
이런 식으로 수정해주면 문제를 해결할 수 있따! 이와 관련된 자료를 단 하나도 찾을 수가 없어서 요게 정석인지는 정말 모르겠다. 일단 UIWindow를 여러개 사용한다거나 윈도우의 hitTest를 오버라이드해서 사용하는 것도 흔치않은 사례라고 하니...
디버깅하면서 뷰들의 주소값으로 어떤 뷰인지 알아내거나, 기기별로 뷰 계층구조의 차이가 있을 수 있다는 것을 알게 되었다~ 계층 구조간 UIView 하나만큼의 차이가 발생한 이유도 정확히는 모르겠지만 아이패드가 멀티 씬을 지원하기 위해 존재하는 UIView가 아닐까까지 추측하는 것으로 오늘의 레슨
끗-🧞