Xcode 프로젝트를 만들면 AppDelegate와 SceneDelegate가 존재한다 이 클래스는 UIResponder를 상속받게된다.
https://developer.apple.com/documentation/uikit/uiresponder
<# 공식문서 내용 #>
이벤트에 응답하고 처리하기 위한 추상 인터페이스이다.
UIResponder는 터치, 동작 및 키보드 이벤트와 같은 사용자 이벤트에 응답하는 개체의 기본 클래스이다. 즉 애플리케이션의 뷰 계층 구조에 있는 개체로 이벤트를 처리하고 전달하는 역할을 한다.
Responder객체는 UIResponder의 인스턴스이다. 그리고 이 인스턴스가 UIKit에서 이벤트 처리의 중추 역할을 한다. UI의 많은 객체들 UIApplication, UIView, UIViewController같은 객체들이 모두 Responder이기도 하다. 이벤트가 발생하면 UIKit은 이벤트를 Responder객체에게 전달해서 처리한다.
화면을 터치하거나 제스처를 취하는 등 여러가지 이벤트가 있다. 어떠한 특정 이벤트를 처리하려면 반드시 해당 이벤트에대한 메서드를 Responder객체가 오버라이드해서 내용을 구현해야한다. touchesBegan, touchesMoved같은 메서드를 뷰 컨트롤러와 UIView에 정의할 수 있었던 것은 모두 이 객체들이 Responder이기 때문이다. 예를들어 터치 이벤트가 발생하면 responder객체는 UIKit에서 제공하는 정보를 기반으로 앱의 인터페이스를 업데이트한다.
이벤트를 처리하는것 뿐만 아니라 UIKit의 responder들은 자신이 처리하지 않는 이벤트를 앱의 다른요소들에게 전달하는 역할또한 수행한다. 만약 어떤 responder가 이벤트를 처리하지 않으면 이 객체가 Responder Chain의 다음 responder에게 이벤트를 전달한다. Responder chain은 UIKit에의해 미리 정해진 규칙에 따라 동적으로 관리된다. 예를 들어 View는 자신의 super view에게 이벤트를 전달하게되고 UIView는 ViewController에게 전달한다.
Responder 객체들은 UIEvent 객체들을 처리하지만 input view를 통해서 커스텀 입력을 받을 수도 있다. 가장 대표적인 custom input의 예시는 키보드이다. 사용자가 화면에 있는 UITextField와 UITextView를 탭하면 해당 뷰는 First Responder가 되어 키보드(입력뷰)를 표시한다. 이처럼 개발자는 커스텀 입력 뷰를 만들어서 어떤 responder객체가 횔성화 되면 화면에 표시하도록 할 수 있다.
여기까지가 공식문서의 내용
내용을 요약하자면,
1. UIResponder는 이벤트가 발생하면 처리해서 내용을 구현하는 일을 한다.
2. UIView, ViewController등 많은 UIKit객체는 UIResponder이다.
3. 이벤트를 처리하는일 뿐 아니라 자신이 처리하지 않는 이벤트는 Responder Chain규칙에 의해 정해진 다음responder에게 이벤트를 전달하는 역할을 한다.
3. input view를 통해 커스텀 입력을 받을 수 있다.
Responder는 이벤트를 전달받았으면 그것을 처리하거나 다른 Responder객체로 넘겨주어야 한다. 앱이 이벤트를 전달 받았을 때 UIKit은 자동으로 이벤트를 처리하기에 가장 적절한 Responder 객체로 이벤트를 전달한다.
이벤트를 처리하기에 가장 적절한 Responder 객체를 FirstResponder라고 한다.
이를 활용한다고 해보면 키보드에서 엔터를 눌렀을 때 다음 텍스트 필드로 이동하기 위해 becomeFirstResponder를 실행하는 경우를 생각해보면 이해가 쉽다.
예를 들어 터치이벤트를 처리하려면 클래스가 UIResponder에서 상속한 적절한 메서드를 정의해야한다.
터치 이벤트를 처리하려면 클래스에서 touchesBegan(_:with:) 메서드를 구현하고 뷰 또는 컨트롤의 범위 내에서 터치가 발생했는지 확인해야한다.
touchesBegan(_:with:) - 터치 이벤트가 시작될 때 호출됨
touchesMoved(_:with:) - 터치 이벤트가 움직일 때 호출됨
touchesEnded(_:with:) - 터치 이벤트가 종료되면 호출됨
touchesCancelled(_:with:) - 터치 이벤트가 취소될 때 호출됨
Responder Chain 구조
이처럼 UILabel, UITextfield, UIButton이 있는 앱이 있다고 할 경우
UITextField가 어떤 이벤트를 받았을 때 UITextField가 이벤트를 처리하지 못한다면 UIKit은 이 이벤트를 UITextView의 상위 뷰인 UIView로 전달하게 된다. 여기서 이벤트가 처리되지 못하면 그 상위뷰인 UIView에 전달되고, 이 뷰와 연결된 UIViewController를 거쳐서 UIWindow까지 전달된다. 여기서도 이벤트가 처리되지 못하면 UIApplication까지 올라갈 수 도 있다.
이 메서드들은 responder chain을 관리해주는 메서드들이다. 간단하게 설명하자면 아래와 같다.
- becomeFirstResponder: window의 첫 번째 responder로 만들기 위해 사용된다.
- resignFirstResponder