[iOS] Responder Chain / Touch Event

Youngwoo Lee·2021년 8월 15일
0

iOS

목록 보기
22/46
post-thumbnail
post-custom-banner

Responder, Responder Chain이해하기

야곰 캠프 활동학습 중 나온 주제이다. 개발자 문서에서 빈번하게 등장하는 Responder Chain 개념에 대해서 알아보자!

Responder and UIResponder

Responder는 이벤트를 핸들링하고 이벤트에 반응할 수 있는 객체이다. 아래를 보면 UIViewUIResponder를 상속하고 있는 것을 볼 수 있다. UIApplication, UIViewController, UIWindow 를 포함한 많은 중요 객체 또한 responder이다

이벤트 종류로는 터치, 모션, 원격 조정(ex: 에어팟을 통한 원격조정) 이벤트 등이 있다. UIResponder 메서드에 위 이벤트 종류별 대응되는 메서드들이 있다. 해당 메서드를 오버라이드해서 구현하면 된다. 터치 이벤트를 핸들링하기 위해서는 touchesBegan(_: with:) 와 같은 메서드를 구현해야된다.



UIResponder 의 메서드는 아니지만 UIView 의 메서드인 hitTest(_:with:) 의 경우 touchesBegan(_: with:) 와 같이 해당 View가 터치되었을 경우 호출된다


touchesBegan의 경우는 UIResponder의 메서드라는 점, hitTest는 UIView에서 정의된 메서드라는 점이 차이점이지만, 또 다른 차이점이 있다. 다른 차이점은 일단은 남겨두고 밑에서 알아보자!



The Responder Chain

이벤트 핸들링 말고도, UIKit responder들은 처리되지 않은 이벤트를 다른 항목으로 미루는 일도 담당한다. Responder chain은 responder 객체들이 이벤트나 액션 메시지를 핸들링할 책임을 앱의 다른 객체들에게 전송할 수 있도록 해준다. 특정 정해진 responder가 이벤트를 핸들링하지 않을 경우, 해당 responder는 그 이벤트를 responder chain의 다음 객체에게로 포워딩한다. 메시지는 처리될 때까지 계속 chain의 상위 객체들로 이동한다. 마지막까지 처리되지 않을 경우, 앱이 해당 메시지를 버린다.

위 그림처럼 responder chain path는 일반적으로 정해져 있다. 뷰(first responder)를 시작으로 ViewController, UIWindow, UIApplication 까지 올라간다.



위 그림을 직접 눈으로 확인해보기 위해서, Xcode에서 구현해봤다.

빨간색으로 표시되어 있는 RedView를 터치했을 경우, 해당 View 가 FirstResponder 이지만 이벤트에 대한 핸들링을 해주지 못하므로 상위 View의 touches began 메시지가 출력되는 것을 볼 수 있다


그렇다면 FirstResponder인 요소가 이벤트에 대한 핸들링을 해준다면??? 어떻게 될까?? Responder Chain 에 따라 상위로 올라가지 않겠지??

실제로 위 사진의 TextField 를 터치 했을 경우 시스템 키보드가 올라오면서 이벤트 핸들링이 이뤄지기 때문에 Responder Chain 에 따라 상위로 올라가지 않는다~

오? 근데 보면 hitTest는 꾸준히 출력이 되네??~
이를 통해서 hitTestFirst Responder 에서 이벤트 핸들링이 이뤄진다고 해도 무조건 실행되어야 하는 로직이 있을 경우 해당 메서드에서 작성해주면 될 것이라는 예측?, 기대?를 해보면 될 것 같다!


Gesture Recognizer
Tap Gesture Recognizer를 위 코드에서 실행시켜보면 알겠지만, Gesture Recognizer가 올려져 있는 View가 First Responder가 될 가능성?이 없을 경우에 실행되지 않는 것을 알 수 있다. Gesture Recognizer 는 Responder Chain과는 별개이며, UIResponder 메서드가 실행된 이후에 제일 마지막에 호출되는 것도 기억하자!



정리

iOS 환경에서 사용자의 터치 이벤트를 알아채거나 제어할 수 있는 방법

  • Gesture Recognizer를 이용해서 터치 이벤트 제어
  • UIResponder의 각 이벤트에 대한 처리 Method
  • UIView의 hitTest Method

View 위에 Tap Gesture Recognizer가 존재할 때, 사용자가 뷰 영역을 터치하면 터치 이벤트를 가장먼저 수신하는 주체는 누구?

터치가 됐을 때 View랑 Tap gesture recognizer중에 어떤 친구가 먼저 반응할까?

hitTest → touches → Tap Gesture Recognizer

  • 그 안에서는 Responder Chain의 super → subclass 순서로 반응함!
  • textField처럼 응답해서 처리해야할 친구가 생기면 chain이 끊김 (그래도 hitTest는 다 반응함)
    • 근데 왜 responder chain에 없는 tap gesture recognizer도 반응을 안하는가??
      • 자신이 속한 뷰가 First Recognizer일 때만 반응하는구나?! 좋구나!
    • HitTest는 무조건 반응하기에, 강제로 터치 영역을 제한하는 경우에 사용하면 좋을듯.
  • touches 이벤트를 오버라이드할 때, super를 호출하지 않으면 touch event를 처리하는 다른 메서드를 반드시 모두 오버라이드해야한다. ⇒ super 꼭 호출해야함. 왜?? -> 공식문서 참고

Apple Developer Documentation

iOS 환경에서 일으킬 수 있는 이벤트의 종류

  • Touch Events
    • Tap - A fingertip touches the screen and lifts up.
    • Pinch - Two fingertips come together or move apart.
    • Rotation - Two fingertips rotate left or right in a circular motion.
    • Pan - A fingertip slides in a dragging motion across the screen.
    • Swipe - A fingertip slides up, down, left, or right across the screen and lifts up.
    • Screen edge pan - A fingertip slides in a dragging motion that starts near the edge of the screen.
    • Long press - A fingertip touches and presses down on the screen.
  • Press Events
  • Shake Motion
  • Remote Control
  • Editing Menu Message


참고자료

profile
iOS Developer Student
post-custom-banner

0개의 댓글