관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] HitTest 개념 (first responder, responder chain) 본문

iOS 기본 (swift)

[iOS - swift] HitTest 개념 (first responder, responder chain)

jake-kim 2021. 2. 9. 01:27

Hit Testing이란?

  • 터치 이벤트가 발생한 최상단 뷰를 찾는 행위 -> 찾는 이유: First Responsder (해당 이벤트를 처리할 수 있는 첫 번째 뷰를 탐색하는 것)

Hit Testing 동작 원리

  • 최상단 뷰 탐색(역순 탐색): 상식적으로 사용자가 탭한건 가장 위에 얹어진 뷰라고 생각할 수 있지만, Hit Testing은 가장 밑에 깔린것부터 탐색
  • 현재 MainView위에 Subview1, Subview2가 sibling을 이루고 있다면, 아래와같이 탐색
  • UIWindow -> MainView -> Subview2 -> Subview1
UIWindow -> hitTest(_:with:) 호출 -> 내부적으로 point(inside:with:) 호출
// point(inside:with)로 현재 터치 이벤트가 발생한 지점이 UIWindow내부인지 판단, 내부이면 true 반환 -> 그의 subviews 탐색(MainView)
  • false, alpha값이 0.01 미만인 뷰의 검사는 진행하지 않음(해당 뷰의 subviews또한 검사 x)
  • 위처럼 탐색하다가 true를 반환했는데 subviews가 없으면 해당뷰가 first responder가 되어서 event를 처리할 자격이 주어짐
  • 단, first responder 자격이 없는 경우 다시 되돌아가면서 first responder를 찾는 과정 진행
  • 핵심은 Hit Testing이 끝난 후 다시 진행된 역순으로 Responder Chain을 실시
  • 아래 내용 확인: ios-development.tistory.com/311


hitTest 응용

  • PassThroughView: 터치 이벤트는 자신이 아닌 subView들이 받도록 설정
    - container는 map이고 각 child들은 PassThroughView이고 hitTest를 구현하여 container가 선택되게끔 설정
  • hitTest에서 nil반환의 의미: superview가 터치 이벤트를 받을 수 있도록, 해당 뷰 (subview)가 터치되면 nil을 반환하고 다른 뷰일경우 UIView를 반환
class PassThroughView: UIView {
  override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let hitView = super.hitTest(point, with: event)
    // superview가 터치 이벤트를 받을 수 있도록,
    // 해당 뷰 (subview)가 터치되면 nil을 반환하고 다른 뷰일경우 UIView를 반환
    return hitView == self ? nil : hitView
  }
}

 

Comments