ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • UIResonder & Responder Chain
    iOS 2022. 3. 17. 17:58

    안녕하세요.

    오늘은 UIResponder와 Responder Chain에 대해서 알아보겠습니다.


    1. UIResponder

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

     

    Apple Developer Documentation

     

    developer.apple.com

    Responder Chain을 이해하기 위해서는 먼저 UIResponder에 대해서 알아야 합니다.

     

    UIResponder는 이벤트에 반응하고 처리하기 위한 추상 클래스입니다.

     

    UIKit이 제공하는 대부분의 객체들이 UIResponder를 상속받고 있습니다.

     

    UIView, UIViewController 심지어 UIApplication까지 UIResponder를 상속하고 있다!

    UIResponders는 다양한 이벤트들을 처리하기 위한 메서드들을 제공하고 있습니다.

     

    자주 사용해본  touchesBegan(_:with:)과 같은 터치 이벤트들 이외에도 모션 이벤트, 프레스 이벤트, 원격 조종 이벤트들을 위한 메서드들도 제공하고 있습니다.


    2. Responder Chain

    그렇다면 Responder Chain은 무엇일까요?

     

    Responder Chain은 UIResponder들의 연결 리스트라고 생각하면 됩니다.

     

    UIResponder는 자신이 처리하지 못한 이벤트들을 다음 UIResponder에게 전달합니다.

     

    UIResponder는 next라는 프로퍼티를 가지고 있습니다. 자신이 처리하지 못한 이벤트를 이 next Responder에게 보내는 것이죠.

     

    그리고 First Responder는 이 연결 리스트에서 가장 앞 쪽에 위치한, 이벤트를 가장 먼저 전달받는 UIResponder입니다.

     

    이 Responder Chain은 뷰 계층에 따라 동적으로 관리됩니다.

     

    최상위 뷰(z축의 가장 위에 존재하는 뷰)부터 UIApplicationDelegate까지 이벤트를 처리할 수 있는 객체를 확인합니다.

    Responder Chain

    처리하지 못한 이벤트는 무시합니다.

    (Storyboard에서 임의로 IBAction을 지정한 후 해당 IBAction을 제거한 경우에는 Unrecognized Selector라는 에러를 띄웁니다.)

     

    아마 많은 분들이 무의식 중에 Responder Chain을 경험해보셨을 겁니다.

     

    바로 키보드를 내리는 과정을 통해서입니다.

     

    위와 같이 TextField와 회색 뷰를 포함하는 ViewController가 있습니다.

     

    TextField를 터치하게 되면 키보드가 올라옵니다.

    하지만 화면에 다른 곳을 눌러도 키보드는 내려가지 않습니다.

     

    그리고 키보드를 내려주기 위해서 ViewController에서 다음과 같은 코드를 작성하셨을 겁니다.

    final class ViewController: UIViewController {
    
        @IBOutlet weak var textField: UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            super.touchesBegan(touches, with: event)
            self.textField.resignFirstResponder()
        }
    }

    touchesBegan(_:with:) 메서드를 재정의해서 textField가 더 이상 FirstResponder가 아니게 하는 것이죠.

     

    키보드는 Text 입력이 가능한 View가 First Responder여야 화면에 나타나기 때문입니다.

     

    이러면 정상적으로 키보드가 내려가게 됩니다.

     

    그런데 회색 뷰를 터치해도 키보드가 내려가는 것을 확인할 수 있습니다.

     

    분명 ViewController에서 touchesBegan(_:with:)를 재정의했는데 말이죠.

     

    Responder Chain 때문에 이러한 일이 발생하는 겁니다.

     

    회색 뷰는 touchesBegan(_:with:) 메서드가 재정의되어 있지 않기 때문이죠.

     

    만약 회색 뷰를 Custom View로 만들고 touchesBegan(_:with:) 메서드를 재정의해 아무런 동작도 하지 않게 하거나

    class CustomView: UIView {
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            // do nothing
        }
    }

    또는 next Responder를 nil로 만든다면

    class CustomView: UIView {
    
        override var next: UIResponder? {
            return nil
        }
    }

    회색 뷰를 눌렀을 때는 화면이 내려가지 않게 됩니다.


    오늘은 UIResponder와 Responder Chain에 대해서 알아보았습니다.

     

    1. UIResponder는 이벤트에 대해서 반응하고 처리하는 객체이고

     

    2. 이벤트는 FirstResponder부터 처리될 수 있는지 확인하고 Responder Chain을 통해서 처리하지 못한 이벤트를 전달한다.

     

     

     

Designed by Tistory.