iOS는 사용자가 앱을 직관적인 방법으로 사용할 수 있도록 디자인되었다.
따라서 iOS 개발을 하면서 우리는 사용자 경험이 물 흐르듯이 자연스럽게 이루어질 수 있도록 신경써야한다.
그러한 관점에서 앱이 처음 시작되고 종료되어 메모리에서 내려갈때까지의 생명주기인
iOS Application Life Cycle의 각 단계를 잘 이해하고 있어야 한다.
그렇다면
처음에 앱이 시작되면 가장 먼저 불리는 메서드는 무엇일까?
이 메서드는 싱글턴으로 구현된 UIApplication 객체를 생성하고, UIApplicationDelegate 프로토콜을 따르는 delegate를 정의한다.
그리고 app launch, app termination과 메모리 부족 경고같은 중요한 런타임 이벤트들을 delegate에게 알려서 대신 대응하도록 한다.
개발자가 직접 UIApplication을 상속받아서 사용할 필요는 없고 보통 미리 정의되어있는 AppDelegate 객체를 이용해서 시스템과 앱 간의 상호작용을 다룬다.
iOS 12 이전에는 AppDelegate
만 사용하여 Process LifeCycle과 UILifeCycle 둘다 AppDelegate가 관리했으나,
iOS 13부터는
SceneDelegate
가 관리하게 되었다.AppDelegate
가 여전히 관리한다.AppDelegate
가 관리하게 되어 Scene에 관한 정보를 업데이트받는다.그러니깐 다시말해서 앱 전반의 관리는 AppDelegate가, 거기에서 특정 scene의 라이프사이클은 SceneDelegate가 따로 관리한다는 뜻이다.
따라서 iOS 12까지는 하나의 앱에 하나의 window(창) 즉, 한 앱을 동시에 키는 것이 불가능하였지만
iOS 13부터는 window의 개념이 scene으로 대체되고 하나의 앱에서 여러 개의 scene을 가질 수 있게 되었다. 즉, 하나의 앱을 동시에 여러개 키는 것이 가능해졌다.
UIWindow
와 View Controllers
가 포함되어 있음UIWindowSceneDelegate
객체를 가지고 있음UIWindowSceneDelegate
객체를 동시에 활성화 가능UISceneSession 객체는 각 scene의 독립적인 런타임 인스턴스를 관리한다. 유저가 한 앱에 새로운 scene을 추가하게 되면 시스템은 UISceneSession 객체를 생성하여 그 scene을 관리하게 된다. 따라서 각 scene을 만들고 없애는 일련의 과정을 관리하는 것이다.
Session LifeCycle 과 Process LifeCycle
이 두가지를 관리하는 일을 하는데 전자에 관해서는 이전 질문에서 설명을 했으니 후자인 process에 관해 설명하겠다.
라이프 사이클과 각 단계로 전환되면서 호출되는 메서드들을 보기 쉽게 정리해놓은 이미지가 있어서 여기에서 가져왔다.
App Life Cycle
Scene Life Cycle
iOS 13부터 UI LifeCycle에 관해서는 SceneDelegate
가 관리하게 되었다고 했으니 Scene-Based Life-Cycle Events에 대해 자세히 알아보자.
Scene이란 디바이스에서 실행중인 앱의 UI의 인스턴스 중 하나이다. 단일 앱에 대해 여러 Scene을 생성할 수 있고 각각 독립적으로 화면에 띄우고, 숨길 수 있다. 각 Scene은 독립적인 Life Cycle을 가진다.
사용자나 시스템이 앱에 대한 새로운 scene을 요청하면, UIKit는 scene을 생성하여 unattatched 상태로 보낸다. 그리고 나서 사용자가 요청한 경우에는 foreground 상태로 변하지만, 시스템이 요청한 경우에는 background 상태로 보내진다.
사용자가 앱을 사용하다가 UI를 화면에서 없앴을때, UIKit는 scene을 background 상태로 보내고 결과적으로 suspended 상태로 보내게 된다.
그렇게 background나 suspended 상태에 있는 scene은 언제든지 연결이 끊겨서 unattatched 상태로 변할 수 있다.
각 state에 대해서 자세하게 알아보자면,
UIScene
클래스 안에 ActivationState
라는 Enum 타입을 가지고 있다.
extension UIScene {
@available(iOS 13.0, *)
public enum ActivationState : Int {
case unattached = -1
case foregroundActive = 0
case foregroundInactive = 1
case background = 2
}
}
scene
은 처음에 unattached 상태로 시작되며 시스템이 connection notification을 주기 전까지는 계속 이 상태를 유지한다. scene
이 foreground에서 돌아가고 있으며, 현재 event들을 받고 있는 상태이다. active scene의 interface는 화면에 있으며 사용자에게 보여지게 된다.scene
이 foreground에서 돌아가고는 있지만 event를 받지는 않는다.scene
이 다른 상태로 전환되는 동안에 바로 이 foregroundInactive 상태를 통과하게 된다.scene
이 스크린이 아닌 background에서 실행이 되고있는 상태이다.scene
이 background 상태에 있으며, 아무것도 실행되지 않는 상태를 의미한다.실행 중인 앱을 멀티태스킹을 사용하여 Background로 보낸 뒤 다시 멀티태스킹을 사용하여 해당 앱으로 돌아왔을때
실행 중인 앱을 멀티태스킹 창을 띄워 바로 종료하는 경우
백그라운드 상태에 있는 앱을 종료하는 경우
실험 결과 백그라운드에서 앱을 바로 종료하면 applicationWillTerminate 메서드가 불리지 않는다.
실행 중인 앱을 바로 종료하는 경우
그러나 실행 중인 앱을 바로 종료시 불린다.
앱을 quit하는 상황(=> background로 전환하는 상황)에서 불리는 sceneWillResignActive에 저장하는 것이 좋을 것 같다.
왜냐하면 applicationWillTerminate(_:)의 경우 background를 지원하는 앱인 경우 background 상태에서 앱을 종료하면 불리지 않기 때문이다.
공식문서에도 앱을 deactivate하면 불리는 메서드인sceneWillResignActive에서 유저데이터를 저장하라고 한다.
https://developer.apple.com/documentation/uikit/uiapplication
https://developer.apple.com/documentation/uikit/uiapplicationdelegate
https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background
https://velog.io/@dev-lena/iOS-AppDelegate%EC%99%80-SceneDelegate
https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
정리 잘되어 있어서 잘보고 갑니다! 덕분에 도움이 많이 됐어요!!