touchesBegan()에 대해 공부하다 Responder Chain
에 대한 얘기가 나와서 포스팅해본다!
우선 Apple Article을 기준으로 작성했다.
우선 Article의 Overview에 대해 살펴보고 하나씩 알아가보자!
- App은
Responder Object
를 사용해 event를 수신하고 처리한다.Responder Object
는 UIResponder 클래스의 모든 instance이다.Responder
는 raw event data를 수신하고 event를 처리하거나 다른 Responder Object로 전달해야한다.- App이 event를 수신하면 UIKit는 자동으로 first responder인 가장 적절한 Responder Object로 event를 알린다.
- 처리되지 않은 event는
active Resopnder Chain
안에 있는 Responder에서 다른 Responder로 전달된다.
Overview를 읽어보면 Responder Object
가 반복적으로 나온다.
Resopnder Object
에 대해서 먼저 알아보자!
Responder
는 event를 핸들링하고 event에 반응할 수 있는 객체이다.
Responder Object
는 UIResponder에서 상속된 class들의 instance이다.Responder
이다.event가 발생하면 UIKit는 event 핸들링을 위해 App의 Responder Object
에게 event를 전달한다.
event의 종류에는 Touch, Press, Shake-motion, Remote-control, Editing menu message가 있다.
이 부분에 대해서는 아래에서 다시 한 번 다뤄보자!
위와 같은 종류로 나눠진 event들을 핸들링하기 위해서는 Responder
가 해당 event에 대응되는 Method들을 override하여 구현해야 한다.
우리는 이전 포스팅에서 다뤘던 touchesBegan(_:with:)
, touchesMoved(_:with:)
, touchesEnded(_:with:)
, touchesCancelled(_:with:)
Method를 override해서 touch event를 핸들링했다.
(touch event는 Responder에서 touch의 변화를 트래킹하고 App의 interface를 적절히 업데이트하기 위해 UIKit에서 제공하는 event 정보를 이용한다.)
우리는 Responder
가 무엇인지 알았다.
event를 핸들링하고 event에 반응할 수 있는 객체
Responder
에서 처리되지 않은 event는 active Responder Chain
안에 있는 Responder에서 다른 Responder로 전달된다는데 Responder Chain
은 뭘까?
Responder
들은 event 핸들링 뿐만 아니라 처리되지 않은 event를 App의 다른 곳으로 forwarding하는 일도 한다.Responder Chain
은 event나 액션 메시지를 App의 다른 Object로 전송해서 핸들링하도록 한다.Responder
가 event를 핸들링하지 않을 경우, 해당 Responder
는 event를 Responder Chain
으로 엮인 다음 Object에게로 forwarding한다.Article에서는 아래의 그림을 통해 Responder Chain
을 설명한다.
우리도 아래의 그림으로 event가 Responder Chain
을 따라 이동하는 내용을 따라가보자.
1개 label, 1개 textField, 1개 button, 2개 background view로 이뤄진 화면이 있다.
textField
가 event를 핸들링하지 않으면, UIKit는 textField의 부모인 UIView 객체
에게로 event를 보낸다.UIView
에서도 event가 핸들링되지 않으면 window의 root view
에게로 event를 보낸다.root view
에서 Responder Chain
은 event를 UIWindow로 보내기 전에 root view
를 소유하고 있는 view Controller
에게로 event를 보낸다.window
가 event를 처리하지 못하면 UIKit는 event를 UIApplication 객체
에게로 보낸다.app delegate
가 UIResponder의 인스턴스이고 이전에 event를 받은 적이 없다면 app delegate
까진 전달된다.이런 과정을 통해 event가 핸들링될 때까지 상위로 이동하는 모습을 볼 수 있다.
UIKit는 받은 event의 종류에 따라서 특정 객체를 해당 event의 first responder
로 지정한다.
Responder
가 event를 받으면 이를 반드시 처리하거나, 다른Responder
가 처리할 수 있도록 넘겨야한다.
App이 event를 받으면 UIKit는 적절한Responder
를 지정해서 event를 넘겨 처리를 하게 한다.
이 처음으로 event를 받는Responder
를first responder
라고 한다.
즉 event를 처음으로 받을 (UIKit가 지정한) 적절한Responder
가first responder
라고 할 수 있다.
그렇다면 이렇게 표현할 수도 있을거 같다.
first responder
가 event를 처리하지 못한다면 처리할 수 있는Responder
가 나올 때 까지 연쇄적으로Responder Chain
으로 연결된 다음Responder
에게 넘어간다.
App에서 event를 처음 받는 Responder
객체를 first responder
라고 했다.
event를 받기 위해서 Respnoder
는 자신이 first responder
가 될 수 있음을 나타내야 한다.
first responder
가 될 수 있게 하려면 UIResponder
의 subClass에서 canBecomeFirstResponder
프로퍼티를 override하여 true를 반환하도록 만들어야 한다.
Responder
는 event message를 수신하는 것 이외에 target이 특정되지 않은 action message들을 받을 수도 있다.
(action message는 button이나 사용자가 조절 가능한 control과 같은 control들로부터 송신된다.)
사용자가 textField
를 touch해 event가 발생했으므로 textField
가 first responder
가 될 것이다.
action message
를 이용해 소통한다.action message
는 event는 아니지만 Responder Chain
을 이용한다.first responder
에서 시작하여 적절한 action message를 구현한 객체를 만날 때까지 Responder Chain
을 따라 이동한다.Gesture Recognizer
또한 touch 등을 인식하지 못하면 UIKit는 view로 touch를 보내고 view도 touch를 처리하지 않을 경우 마찬가지로 Responder Chain
을 따라 event를 보낸다.UIKit는 어디서 touch event가 발생했는지 결정하기 위해 view 기반 hit-testing
을 사용한다.
UIKit는 touch 위치를 view 계층에 있는 view 객체의 bound와 비교한다.
UIView의 hitTest(_:with:)
Method는 특정 touch를 포함하는 가장 깊은 subView를 찾기 위해 view 계층을 따라서 이동한다.
이 가장 깊은 subView가 touch event의 first resopnder
가 된다.
touch 위치가 view의 경계(bound) 밖이라면 hitTest(_:with:)
Method는 해당 view와 그 view의 모든 subView들은 무시한다.
결과적으로 view의 clipToBounds
프로퍼티가 false라면 그 view의 밖에 있는 subView들은 touch를 포함하더라도 반환되지 않는다.
touch가 발생하면 UIKit는 UITouch
객체를 만들고 view와 연결한다.
touch 위치나 다른 파라미터들이 변경되면 UIKit는 같은 UITouch
객체를 새로운 정보로 업데이트한다.
이때 변경되지 않는 유일한 프로퍼티는 view
이다.
touch 위치가 원래 view의 바깥으로 이동하더라도 touch의 view
프로퍼티는 변하지 않는다.
touch가 끝나면 UIKit는 UITouch
객체를 메모리에서 해제한다.
Responder
객체의 next 프로퍼티를 override해 Responder Chain
을 변경할 수 있다.
이때, next responder
는 override한 프로퍼티에서 반환하는 객체이다.
많은 UIKit class들은 이 프로퍼티를 override하여 특정 객체들을 반환하고 있다.
view
가 view controller
의 root view
라면 next responder
는 view controller
이다. next responder
는 해당 view의 super view
이다.view controller
의 view
가 window
의 root view
라면 next responder
는 window object이다.view controller
가 다른 view controller
에 의해 present
된 경우 next responder
는 presenting view controller
이다.next responder
는 UIApplication Object
이다.UIApplication Object
의 next responder
는 app delegate
이다.app delegate
가 UIResponder
의 instance면서 view, view controller 또는 App Object 자신이 아닐때만 해당된다.