어플리케이션을 실행하면 디바이스의 메모리에 UIApplication 클래스의 객체가 생성된다. 이 객체는 Singleton 객체로, 어플리케이션과 관련된 Events를 관리한다. 특정 event가 발생하거나 어플리케이션의 상태가 변화하면 자신의 Delegate에게 알려주고 처리를 맡긴다. 어떻게 알려줄까? UIApplicationDelegate 프로토콜에 미리 정의되어 있는 메소드를 통해! 따라서 이 프로토콜은 자신의 Delegate가 상속받은 상태여야 한다.
이벤트를 제어하거나 상태변화를 관리할 때 주로 이용하며, 어플리케이션의 가장 베이스가 되는 뷰인 window를 관리하기도 한다. 어플리케이션의 거의 모든 영역에 영향을 미치는 코드이다.
➡️ AppDelegate.swift
application
: application 파라미터로 전달되는 객체가 바로 이 Delegate에 일을 시키는 UIApplication 객체이다.launchOptions
: 어플리케이션이 어떻게 실행되었는지에 대한 정보(ex. push 알람을 터치해서 진입했는지, 다른 앱을 통해 진입했는지 등)가 딕셔너리 형태로 들어온다.중지 (Not running)
: 실행되지 않았거나 시스템에 의해 종료된 상태비활성화 (Inactive)
: 화면에 어플리케이션이 보여지고 있긴 하지만 다른 이벤트에 의해서 이벤트를 받지 못하고 있는 상태 (ex. Alert로 인해 뒤에 가려져 있는 경우 등)활성화 (Active)
: 어플리케이션이 보여지고 있으며 사용자와 이벤트를 주고받는 상태백그라운드 (Background)
: 홈버튼을 눌렀거나 다른 어플리케이션으로 전환되어 백그라운드에서 실행되는 상태일시중지 (Suspended)
: 어플리케이션이 백그라운드 상태에서 더이상 실행할 코드가 없어 백그라운드에 머물러있는 상태. 이 상태가 지속되거나 시스템 메모리가 부족하면 시스템은 이 어플리케이션을 종료시켜 중지상태로 보낸다.➡️ SceneDelegate.swift SceneDelegate는 기존 AppDelegate에서 총괄하던 기능이 분리된 것이다.
AppDelegate는 앱시작과 같은 애플리케이션 수준의 이벤트를 처리하고,
SceneDelegate는 UISceneSession의 장면 생성, 파괴 및 상태 복원과 같은 장면의 생명주기 이벤트를 담당한다.
ViewController는 따로 Delegate를 두지 않고 뷰의 상태가 변경될 때마다 자신의 상태변화 메소드를 호출한다.
모든 메소드의 내부에는 super 키워드를 이용해 부모메소드를 호출해야 한다. 이 클래스를 다시 상속해서 서브클래스를 만들더라도 호출체인을 잃지 않기 위함이다.
또, 상태변화 메소드는 절대 호출해서는 안 된다.
응답체인
이란 응답객체
가 받은 이벤트를 최종 목적지까지 전달하는 일종의 계층체계를 의미한다.
보다시피 UIView는 UIResponder 클래스를 상속받는다. 따라서 응답객체
가 될 수 있다. 응답객체
는 자신이 응답을 할 수 있는 상황이고, 발생한 이벤트가 응답을 할 수 있는 이벤트면 응답을 받아서 처리한다. 그렇지 않다면 응답체인
상의 자신의 다음 순위에 있는 응답객체
에게 응답권한을 넘겨준다.
대체로 뷰 (UIView)
는 자신의 부모뷰 (ex. UIStackView)
에게 응답권한을 넘겨주고, 부모뷰가 없다면 윈도우 (UIWindow)
나 뷰컨트롤러 (UIViewController)
에게 넘겨준다. 이들이 처리할 수 없는 이벤트라면 어플리케이션 객체 (UIApplication)
에게 넘겨주고, 어플리케이션 객체는 이벤트를 보고 처리할 것이 없다면 그냥 무시하며 딜리게이트에서 처리해야 하는 이벤트라면 딜리게이트 (UIApplicationDelegate)
로 넘겨준다.
이렇게 이벤트를 처리할 응답객체가 나타날 때까지 응답체인을 따라 이벤트가 전달된다.
FirstResponder 또한 알아두어야 할 개념인데, 일반적으로 이벤트나 액션을 수신하는 응답자 체인의 첫 번째 객체를 말한다. 대부분의 경우 FirstResponder는 사용자가 마우스나 키보드로 선택하거나 활성화하는 뷰 객체이다.
🌟 예시
View 영역을 잡고 Inspector를 켜보자. Custom Class를 적용해줄 것이다.
touchesBegan, touchesMoved, touchesEnded는 UIResponder에 정의되어 있는 메소드다. 우리의 CustomView 클래스는 UIView를 상속받고 있고, 이 UIView가 UIResponder를 상속받기 때문에 이 메소드들을 쓸 수 있다.
쨘 View에 Custom Class로 우리의 CustomView를 적용해줬다.
이제 시뮬레이터를 돌려보자.
TextField와 Button이 아닌 비어있는 뷰를 터치했다가 드래그했다가 마우스를 떼니 차례로 began, moved, ended가 호출되는 모습이다.
TextField나 Button을 터치하면 이 메소드들이 호출되지 않는다. 뷰에서 응답권한을 받아야 이 메소드들이 호출되는데, TextField와 Button에서 이 이벤트를 처리할 수 있으므로 더이상 응답체인에 있는 다른 응답객체(뷰, 윈도우, 뷰컨트롤러, ...)로 전달하지 않기 때문이다.
하지만 만약 이 TextField와 Button의 User Interaction Enabled 체크박스를 off로 바꿔준다면?!
TextField나 Button을 터치했을 때 이 메소드들이 호출되는 모습이다. TextField와 Button이 사용자와 상호작용할 수 없게 되어 응답할 수 있는 상태가 아니기 때문에 응답권한을 부모뷰에게 넘겼고, 이 뷰에서 우리가 작성해둔 터치이벤트 메소드가 실행된 것이다.