꿈돌이랜드

[iOS] Responder와 Responder Chain 이해하기 본문

Programming/iOS

[iOS] Responder와 Responder Chain 이해하기

loinsir 2023. 6. 13. 16:42
반응형

본 포스트는 애플 공식 문서를 기반으로 작성했습니다.

UIResponder

이벤트를 핸들링하고 처리하기 위한 추상 인터페이스 입니다.

Responder란 이벤트를 핸들링하고 이벤트에 반응할 수 있는 객체입니다. Responder 객체는 UIKit로 이뤄진 앱의 이벤트 핸들링 뼈대를 이룹니다. 많은 핵심 오브젝트는 또한 UIApplication 객체, UIViewController 객체, UIWindow를 포함한 UIView 객체 들을 포함합니다. 이벤트가 발생하면 UIKit는 핸들링 하기 위해 그것들을 앱의 responder 객체로 가져옵니다.

여러 이벤트가 있을 수 있습니다. 터치 이벤트, 모션 이벤트, 원격 제어 이벤트, 버튼 누르기 이벤트를 포함합니다. 특정 타입의 이벤트를 제어하기 위해, 리스폰더는 반드시 상응하는 메서드를 오버라이드 해야 합니다. 예를 들어 터치이벤트를 제어하기 위해선, touchesBegan, touchesMoved 등의 메서드를 말이죠. 터치의 경우에는 리스폰더가 UIKit에 의해 제공된 이벤트 정보를 터치의 변화를 추적하고 앱 내 인터페이스를 적절하게 업데이트 하기 위해 사용합니다.

이벤트 핸들링 외에도, UIKit responder는 또한 처리되지 않은 이벤트를 앱의 다른 부분으로 전달하는 것도 관리합니다. 지정된 responder가 이벤트를 처리하지 않으면 해당 이벤트를 responder 체인의 다음 이벤트로 전달합니다. 예를 들어 뷰의 경우 이벤트를 처리하지 않으면 자신의 superview로 이벤트를 넘깁니다, 또한 만약 계층의 rootview가 이벤트를 처리하지 않을 경우, 그것은 자신의 상위 view controller로 이벤트를 넘깁니다. 이것이 바로 responder chain 입니다.

Responder는 UIEvent 객체를 처리할 뿐만 아니라 input view를 통한 커스텀 입력 또한 받아들일 수 있습니다. 시스템 키보드는 input view의 명확한 예시입니다. 사용자가 화면 위의 UITextField 나 UITextView 객체를 탭 했을때, view는 first responder가 되고 그것의 input view인 시스템 키보드를 표시합니다. 비슷하게, 커스텀 input view를 만들고, 다른 responder들이 활성화 되었을 때 표시할 수 있도록 할 수 있습니다. responder와 함께 커스텀 input view를 연결하려면, responder 의 inputView 프로퍼티에 해당 view를 할당하세요.


앱은 responder 객체를 사용해 이벤트를 받고 핸들링합니다. responder 객체는 UIResponder 클래스의 인스턴스 이고, 보통 UIView, UIViewController, UIApplication의 서브클래스입니다. Responder 들을 raw event data를 받고 핸들링 하거나 다른 responder 객체로 넘깁니다. 앱이 이벤트를 받으면, UIKit은 자동으로 가장 적절한 responder object를 가리킵니다. 이 객체를 first responder 라 합니다.

핸들링 되지 않은 이벤트는 활성화된 responder chain을 따라 responder에서 responder로 보내어집니다. 이는 앱 responder 객체의 동적 구성입니다. 아래 이미지는 인터페이스에 label, text field, button, 2 개의 배경 뷰가 포함되어 있는 앱의 responder를 보여줍니다. 다이어그램은 또한 이벤트가 어떻게 한 responder에서 responder chain을 따라 다음으로 이동하는지 나타냅니다.

만약 text field가 이벤트를 핸들링하지 않으면, UIKit은 이벤트를 text field의 부모 UIView 객체로 보낸 다음, window의 root view로 보냅니다. root view 로부터, responder chain은 이벤트를 window로 보내기 전에 소유한 view controller로 전환합니다. 만약 window가 이벤트를 핸들링 할 수 없으면, UIKit은 이벤트를 UIApplication 객체로 보냅니다, 그리고 만약 이것이 UIResponder의 인스턴스이고, 아직 responder chain을 이루고 있지 않은 경우 UIApplicationDelegate로 보낼 수 있습니다.

이벤트의 first responder를 결정하기

UIKit는 해당 이벤트 유형에 따라 이벤트에 대한 first responder로 객체를 지정합니다. 이벤트 유형은 다음과 같습니다:

단, 가속도계, 자이로스코프 및 자력계와 관련한 모션 이벤트는 responder chain을 따르지 않습니다. 대신 core motion은 이러한 이벤트를 지정된 객체에 직접 전달합니다.

컨트롤은 작업 메시지를 사용해서 연결된 대상 객체와 직접 상호작용합니다. 사용자가 컨트롤과 상호 작용할 때 컨트롤은 대상 객체에 작업 메시지를 보냅니다. 작업 메시지는 이벤트는 아니지만 응답자 체인을 활용할 수 있습니다. 컨트롤의 타겟 객체가 nil일 때, UIKit은 타겟 객체로부터 시작해서 적절한 액션 메서드가 구현된 객체를 찾을때 까지 responder chain을 순회합니다. 예를 들어 UIKit 편집 메뉴는 이 동작을 사용해 cut(), copy(), paste() 같은 메서드가 구현된 객체를 찾을 수 있습니다.

Gesture recognizer는 touch와 press 이벤트를 view보다 먼저 받습니다. view의 gesture recognizer가 일련의 터치를 인식하지 못하면 UIKit이 터치를 view로 보냅니다. view가 터치를 처리하지 않으면 UIKit은 responder chain 위로 터치를 전달합니다.

터치이벤트가 포함된 responder 결정

UIKit는 view 기반의 hit-testing을 사용하여 어떤 터치 이벤트가 발생했는지 결정합니다. 특히 UIKit는 터치 위치를 view 계층 구조의 view 객체 경계와 비교합니다. UIView의 hitTest(_:with:) 메서드는 터치 이벤트에 대한 first responder가 되는 지정된 터치가 포함된 가장 깊은 하위 뷰를 찾는 view 계층 구조를 순회하는 메서드 입니다.

만약 터치 위치가 view 경계의 바깥이라면, hitTest 메서드는 그 해당 뷰와 그 하위뷰를 모두 무시합니다. 그 결과, 만약 view의 clipsToBounds 프로퍼티가 true라면, 해당 view의 경계 바깥에 있는 subview들은 터치되더라도 반환되지 않습니다.

터치가 발생하면, UIKit은 UITouch 객체를 생성하고 그것을 view와 연결짓습니다. 터치 위치 또는 기타 변수가 변경되면 UIKit은 새로운 정보로 동일한 객체를 업데이트 합니다. 변경되지 않은 유일한 속성은 view입니다. (심지어 터치 위치가 원래 뷰의 바깥으로 이동하더라도, 터치의 ‘view’ 프로퍼티 값은 변하지 않습니다. —> 즉 원래 어느 지점부터 터치가 이뤄졌는지는 프로퍼티 값으로 유지된다는 뜻.) 터치가 끝나면 UIKit은 UITouch 객체를 해제합니다.

responder chain 변경

responder 객체의 next 속성을 오버라이드 해서 responder chain을 변경할 수 있습니다. 이렇게 하면 next responder는 return한 객체가 됩니다.

많은 UIKit 클래스가 이 속성을 오버라이드하고 다음을 포함한 특정 객체를 반환합니다.

  • UIView 객체. 만약 view 자신이 view controller의 루트 view 라면, next responder는 view controller 입니다; 그렇지 않으면 next responder는 view의 superview 입니다.
  • UIViewController 객체.
    • 만약 view controller의 view가 window의 root view 라면, next responder는 window 객체입니다.
    • 만약 view controller가 다른 view controller에 의해 present 되었다면, next responder는 presenting한 view controller 입니다.
  • UIWindow 객체
    • window의 next responder는 UIApplication 객체 입니다.
  • UIApplication 객체
    • next responder는 app delegate 입니다만, 오직 app delegate가 view, view controller, 또는 app 객체 자신이 아니며 UIResponder의 인스턴스인 경우에만 가능합니다.

참고 문서

https://developer.apple.com/documentation/uikit/uiresponder https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events


Uploaded by N2T

반응형

'Programming > iOS' 카테고리의 다른 글

코코아 인터널스 - 2장 메모리 관리  (0) 2023.08.07
코코아 인터널스 - 1장  (0) 2023.07.23
[iOS] 앱 Test 하기  (0) 2023.07.08
[iOS] hitTest 이해하기  (0) 2023.06.14
N2T 테스트 페이지  (0) 2023.05.01