📌 Application의 상태변화와 생명주기

UIApplication

어플리케이션을 실행하면 디바이스의 메모리에 UIApplication 클래스의 객체가 생성된다. 이 객체는 Singleton 객체로, 어플리케이션과 관련된 Events를 관리한다. 특정 event가 발생하거나 어플리케이션의 상태가 변화하면 자신의 Delegate에게 알려주고 처리를 맡긴다. 어떻게 알려줄까? UIApplicationDelegate 프로토콜에 미리 정의되어 있는 메소드를 통해! 따라서 이 프로토콜은 자신의 Delegate가 상속받은 상태여야 한다.

Application Delegate

이벤트를 제어하거나 상태변화를 관리할 때 주로 이용하며, 어플리케이션의 가장 베이스가 되는 뷰인 window를 관리하기도 한다. 어플리케이션의 거의 모든 영역에 영향을 미치는 코드이다.

➡️ AppDelegate.swift

  • application 메소드
    • application : application 파라미터로 전달되는 객체가 바로 이 Delegate에 일을 시키는 UIApplication 객체이다.
    • launchOptions : 어플리케이션이 어떻게 실행되었는지에 대한 정보(ex. push 알람을 터치해서 진입했는지, 다른 앱을 통해 진입했는지 등)가 딕셔너리 형태로 들어온다.
  • applicationWillResignActive 메소드
    • 어플리케이션의 상태변화가 일어났을 때 호출된다.
      먼저 각 상태에 대해 알아보자.
      • 중지 (Not running) : 실행되지 않았거나 시스템에 의해 종료된 상태
      • 비활성화 (Inactive) : 화면에 어플리케이션이 보여지고 있긴 하지만 다른 이벤트에 의해서 이벤트를 받지 못하고 있는 상태 (ex. Alert로 인해 뒤에 가려져 있는 경우 등)
      • 활성화 (Active) : 어플리케이션이 보여지고 있으며 사용자와 이벤트를 주고받는 상태
      • 백그라운드 (Background) : 홈버튼을 눌렀거나 다른 어플리케이션으로 전환되어 백그라운드에서 실행되는 상태
      • 일시중지 (Suspended) : 어플리케이션이 백그라운드 상태에서 더이상 실행할 코드가 없어 백그라운드에 머물러있는 상태. 이 상태가 지속되거나 시스템 메모리가 부족하면 시스템은 이 어플리케이션을 종료시켜 중지상태로 보낸다.

➡️ SceneDelegate.swift SceneDelegate는 기존 AppDelegate에서 총괄하던 기능이 분리된 것이다.

AppDelegate는 앱시작과 같은 애플리케이션 수준의 이벤트를 처리하고,
SceneDelegate는 UISceneSession의 장면 생성, 파괴 및 상태 복원과 같은 장면의 생명주기 이벤트를 담당한다.


📌 ViewController의 상태변화와 생명주기

ViewController는 따로 Delegate를 두지 않고 뷰의 상태가 변경될 때마다 자신의 상태변화 메소드를 호출한다.
모든 메소드의 내부에는 super 키워드를 이용해 부모메소드를 호출해야 한다. 이 클래스를 다시 상속해서 서브클래스를 만들더라도 호출체인을 잃지 않기 위함이다.

또, 상태변화 메소드는 절대 호출해서는 안 된다.


📌 Responder Chain

응답체인이란 응답객체가 받은 이벤트를 최종 목적지까지 전달하는 일종의 계층체계를 의미한다.

보다시피 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이 사용자와 상호작용할 수 없게 되어 응답할 수 있는 상태가 아니기 때문에 응답권한을 부모뷰에게 넘겼고, 이 뷰에서 우리가 작성해둔 터치이벤트 메소드가 실행된 것이다.

profile
기록하는 개발자 👀

0개의 댓글

Powered by GraphCDN, the GraphQL CDN