챌린지 때 간단하게만 보고 지나간 iOS에서 이벤트 처리하는 과정을 다시 한번 학습해보자.
처음은 각 과정에서 등장하는 구성요소의 개념부터 학습해보자.
1. UITouch
가장 간단한 이벤트인 터치 이벤트 객체를 먼저 살펴보자.
일단 터치를 하면 iOS는 UITouch라는 인스턴스를 만들어낸 후, 특정 View에 종속되며
Touch가 종료되는 시점에서 사라진다. 여기서 특정 View는 아마 터치 이벤트를 받은 View로 추측된다.
아래 표를 보면 각 이벤트에 해당되는 first Responder를 정리해 놓은 자료가 있다.
first Responder는 아래에서 설명할테니 어떤 느낌인지만 보자.
이벤트 종류 | First Responder |
Touch events | 터치가 발생한 뷰 |
Press events | 포커싱된 객체 |
Shake-motion events | 개발자 또는 UIkit에서 지정한 객체 |
Remote-control events | 개발자 또는 UIkit에서 지정한 객체 |
Editing menu messages | 개발자 또는 UIkit에서 지정한 객체 |
2. UIEvent
앱에서 하나의 유저 인터렉션을 설명하는 객체
앱은 touch, motion, remote-control 과 같은 여러 타입의 이벤트를 받는다.
이러한 이벤트는 type 와 subtype의 프로퍼티를 통해서 타입을 결정할 수 있다.
유저 인터렉션이 type과 subTpye을 통해서 분류되는 것을 확인할 수 있다.
실제로 type에는 touches, motion , remoteControl, presses 등이 있으며,
subType에는 motion, remoteControl의 이벤트를 조금 더 세분화 해서 분류한 것을 확인할 수 있다.
여러개의 터치를 분석하거나, 유저 인터렉션에 대해서 타입을 분류해서 전달되는 객체라고 정리할 수 있다.
위에서 학습한 UITouch 같은 이벤트가 발생하면 이를 기반으로 UIEvent 인스턴스가 만들아어진다.
3. UIResponder
UIEvent를 받아 처리하기 위한 추상 인터페이스
UIResponder가 이벤트를 받아서 처리한다 ??
우리는 지금까지 이벤트를 잘 처리해왔지만 UIResponder를 만들어 본 적이 없는데 애플이 거짓말을 하고 있는 것인가 ??
정답은 전혀 그렇지 않다. 아래 코드를 봐보자.
@MainActor open class UIViewController : UIResponder
@MainActor open class UIView : UIResponder
UIWindow : UIView
@MainActor open class UIApplication : UIResponder
class AppDelegate: UIResponder,
class SceneDelegate: UIResponder
보면 UIViewController, UIView, UIWindow, AppDelegate, SceneDelegate 보면 모두
UIResponder를 상속 받고 있다.
UIResponder는 총 2가지 역할을한다.
- UIEvent 객체를 받아서 처리한다.
- 해당 UIResponder가 이벤트를 처리를 하지 않으면 다음 UIResponder에게 UIEvent 객체 처리를 넘긴다.
여기서 다음 UIResponder는 어떻게 알 수 있을까 ??
여기서 등장하는 개념이 이번 주제인 UIResponder Chain이다.
4. UIResponder Chain
Chain은 사슬로 무엇인가 연결되어있는 느낌인 것 같다.
Chain의 형태
- view
- superView
- viewController의 최상위 view
- viewController
- window
- UIApplication ..
순서로 진행 되는 것을 볼 수 있다.
다음으로 넘길 때는 UIResponder의 next 프로퍼티를 통해 다음 UIResponder가 있는 지 알 수 있다.
FirstResponder
최초의 Responder
UIResponder의 property와 method를 보면 first responder에 관한 내용이 많은 것을 볼 수 있다.
여기서 자주 쓰이는 becomeFirstResponder와 resignFirstResponder 함수를 학습해보자.
becomFirstResponder
Asks UIKit to make this object the first responder in its window.
말 그대로 호출한 responder가 window first responder가 된다는 뜻이다.
확 와닿지 않는 설명이다. 대표적인 예를 살펴보자.
UITextField를 클릭 시 UITextField는 window의 first responder가 되는데 추측으로는 UITextField가
first responder가 되면 내부적으로 keyboard가 올라오는 동작이 있는 것 같다.
만약 특정 이벤트 시 어떤 responder에게 first responder를 지정하고 싶을 때 사용한다.
resignFirstResponder
becomeFirstResponder와 정확히 반대 되는 동작을 한다.
window의 최초 리스폰더로서의 상태를 그만한다고 요청을 받았음을 알린다.
그러므로 UITextField에서 resignFirstResponder()를 호출하면 키보드가 사라진다.
UITouch 설명 중 나온 표를 보며 이벤트 별 어떤 것이 first responder가 되는 지 다시한번 살펴보자.
5. UIControl
UIControl은 간단히 설명하자면 특정 액션이나 사용자의 의도(드래그, 버튼 클릭 등등)를 전달하는
시각적인 요소들의 기반이 되는 클래다.
UIControl 클래스를 상속하는 클래스로는 대표적으로 UIButton 클래스가 있다.
UIButton의 문서를 UIControl을 상속한다고 명시되어 있다.
@MainActor open class UIButton : UIControl
즉 사용자에게 보여지는 뷰가 보다 사용자와 상호작용할 수 있게끔 능력을 부여해주는 클래스이다.
UIControl 은 Target-Action이라는 매커니즘을 이용해 사용자의 액션들을 앱에 전달한다.
이 Target-Action 매커니즘은 addTarget((_:action:for:)) 메서드를 이용하여 구현한다.
파라미터로 액션을 담당할 객체, 액션에 대한 행위를 정의해준 메서드, 그리고 어느 액션(.touchUpInsider, .valueChanged 등)에 대해 해당 메서드를 호출할 것인지를 넘겨준다.
또한 UIControl 클래스의 속성에는 상태라는 속성이 존재하는데 이 상태는 해당 뷰의 모습과
사용자의 액션에 대한 기능을 결정하는 역할을 한다.
이 상태라는 속성은 사용자의 액션에 대해 원하는대로 직접 구현해줄 수 있다.
당연히 이렇게 설명을 하면 와닿지 않을 수 있습니다. 예를 보자.
위에서 언급했듯이 UIControl을 상속받는 대표적인 뷰는 바로 UIButton 클래스다.
UIButton를 보면 다음과 같은 메소드들을 많이 봤을 것이다.
open func setTitle(_ title: String?, for state: UIControl.State)
open func setTitleColor(_ color: UIColor?, for state: UIControl.State)
open func setTitleShadowColor(_ color: UIColor?, for state: UIControl.State)
open func setImage(_ image: UIImage?, for state: UIControl.State)
open func setBackgroundImage(_ image: UIImage?, for state: UIControl.State)
두번 째 매개 변수로 state를 입력 받는 것을 볼 수 있다.
UIControl을 상속 받는 다면 위와 같이 특정 상태에 따른 별도의 동작을 쉽게 가능케 한다.
참고
'iOS > UIKit' 카테고리의 다른 글
생명주기 (4) [ 업데이트 Cycle ] (2) | 2024.09.01 |
---|---|
생명주기 (3) [ View 생명주기 ] (0) | 2024.09.01 |
UIKit 코드 베이스 셋팅 (0) | 2024.09.01 |
생명주기 (2) [ ViewController 생명주기 ] (0) | 2024.08.31 |
생명주기 (1) [ iOS 앱 생명주기, Scene 생명주기 ] (2) | 2024.08.31 |