iOS의 LifeCycle에 대해선 딱히 별도의 공부나 봐야겠다는 생각은 못했는데, 이번 iOS 공부를 시작하면서 어떤 과정으로 실행되고 종료되는지를 정리 해보면 나름 가치 있는 시간이지 않을까 생각했다.
그리고 최근 iOS 13부터 이상한 Scene이라는 놈이 태어나서 좀 족보가 복잡해졌다랄까나.
아무튼 그 내용도 조금 다뤄보도록 한다.
크게 집중해서 봤던 포스팅들
[Apple Dev Reference] 앱 라이프사이클 The App Life Cycle
일단 앱의 생명주기는 크게 5단계를 거친다.
iOS 프로젝트를 파면 위의 AppDelegate.swift 파일이 생기는데 크게 하는 일은 2가지가 있다.
전체적으로 앱의 Process Lifecycle과 Session Lifecycle(아래 나올 Scene)들을 관리한다.
상당수 App의 state 변화에 따른 메소드들이 Scene으로 이동이 되었다.
앱의 실행 종료, Scene의 관리가 주된 책임이라고 생각을 하면 된다.
상태 변화에 따른 호출 메소드들을 아래에서 볼 수 있다.
///AppDelegate
//앱의 주요 객체를 생성 및 run loop를 만드는 과정들이 끝나기 직전에 호출
func application(
_ application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil)
-> Bool
//앱의 모든 준비가 마무리 되고 실행직전에 보여준다.
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil)
-> Bool
///iOS13이상 SceneDelegate
///iOS12이하 AppDelegate
//유저가 앱을 조작할 수 있게 되었을 때 호출.
//메세지/시스템알림/전화 등이 왔다 없어질 때 호출이 될 수 있으므로 초기화 코드들은 배제하는 것이 좋다.
//멈추어져 있던 타이머/메모리를 많이 먹는 작업 등을 다시 시작하는 코드들을 호출하기에 좋다.
func applicationDidBecomeActive(_ application: UIApplication)
func sceneDidBecomeActive(_ scene: UIScene)
//앱이 Active(앱을 잠시 조작할 수 없게됨/백그라운드로 이동함)등의 상황을 거칠때 호출.
//이 역시 한 주기에서 여러차례 호출 될 수 있으며, 타이머등 리소스를 많이 먹는 작업들을 중지시키거나 메모리에서
//해제 시키는 등의 작업에 적합하다.
func applicationWillResignActive(_ application: UIApplication)
func sceneWillResignActive(_ scene: UIScene)
//앱이 inActive 상태로 진입하게 될 때를 가르킨다.
//다른앱에서 전환해 오거나 앱을 처음 실행하게 되거나 같은 경우들이 있다.
func applicationWillEnterForeground(_ application: UIApplication)
func sceneWillEnterForeground(_ scene: UIScene)
//앱이 Background 상태로 들어갔을 때 호출하게 된다.
//주로 백그라운드 업데이트 등 작업이 필요하게 될 때 호출한다. ex) GPS업데이트 등...
func applicationDidEnterBackground(_ application: UIApplication)
func sceneDidEnterBackground(_ scene: UIScene)
// 몇가지 간혹 볼 수 있는 Delegation
//외부 앱 또는 링크를 열지말지를 리턴하는 함수
//보통 외부 sdk, social login등 구현할 때 자주쓰인다.
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool
//메모리 사용량에 대한 경고
//일반적인 앱을 작업을 할 때 크게 마주하진 않는다.
func applicationDidReceiveMemoryWarning(_ application: UIApplication)
//FCM 등 푸시 작업들을 할 때,
//APNs에서 받은 Token값을 Firebase등으로 넘겨줄 수 있는 함수
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
//FCM을 통해 푸시 노티를 받았을 경우 호출
//이 역시 Firebase로 넘겨주는 호출을 해주게 된다.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])
해당 차이를 알기 위해선 앱의 상태 저장에 대한 기능을 먼저 알아야한다.
앱 상태 복원 (UIViewControllerRestoration)
기본적으로 앱은 언젠가 중지가 되어 앱 라이프사이클의 수명을 다하게 되는데, 이때 최종 ViewController와 그 상태를 저장해 앱을 다시 시작했을 때, 마지막 ViewController와 Data를 그대로 보여주어 유저의 경험을 더 좋게 하고자하는 게 목표인 것 같다.
사실 이게 제대로 이루어지는 서비스를 그렇게 크게 보진 못하지만 애플은 이를 잘하도록 권장하는 것 같다(램을 늘려주면 될텐데...)
Will과 Did의 차이는 마지막에 앱의 상태가 복구가 이루어 졌는지 아직인지에 대한 포인트이다.
왜 Will과 Did중에 Did는 오랜된 것에서 구동이된다 쓰여있으며, Will을 권장하는지에 대한 포인트는 아직 찾지 못했다.
런치옵션에 대한 모든 내용들은 위의 공식문서에 내용이 있다.
해당 정보를 제공해주는 가장 큰 이유는 어떠한 사유로 앱을 시작하게 되었고 그 사유에 따른 런칭 액션들을 할 수 있게 도와주는 것이 목표인 것 같다.
기본적으로 블루투스 데이터 수신, 푸시, 퀵액션 등 다양한 실행할 만한 요소들이 있고 그 요소들의 데이터에 따라 시작 ViewController 들을 달리한다는 등의 기능들을 만들 수 있을 것 같다.
willFinishLaunchingWithOptions에서 return은 보통 true고 되어있고, 또 false로 처리를 하려는 생각은 할 수 없었다. 딱히 필요도 없고.
공식 문서상에는 URL과 몇몇 레퍼를 찾아보니 Launch Options로 들어온 URL들을 OS 에 알리려는 목적이 가장 큰 것 같다. 이 URL은 우리는 처리하지 않을 것이다. 정도의 목적인 것 같은데...
결국 return false를 하더라도 어떠한 영향도 없을 것 같다는 심심한 결론.
iOS 13 이전의 시절에는 없었던 녀석. 왜 필요가 없었나? iOS 앱은 꼭 한개의 세션/화면만 볼 수 있었다.
그러나 아래의 사진과 같은 Multi Window가 생겨나게 되었다.
같은 메모앱을 동시에 2개의 화면으로 실행할 수 있게 된 것이다.
그러므로 이를 대응하기 위해 태어난게 SceneDelegate이다.
여러개의 세션/화면들을 각각 볼 수 있도록 AppDelegate가 하던 일을 어느정도 위임을 받았다.
Scene에는 하나의 인스턴스를 나타내는 windows와 view controllers들이 있다.
Scene은 같은 메모리와 앱 공간을 동시에 실행하면서 즉 위의 아이패드와 같이 여러개의 Scene들이 활성화 될 수 있다.
아래는 기존 AppDelegate에서 하던 몇개의 기능들이 SceneDalegate로 대체되어 1:1 매칭이 되니, 위의 정리를 참고하면 된다.
12이하의 앱들은 무조건 1개의 window를 가지게 되므로 iOS 13에서 추가된 부분을 삭제하고 이전과 설정하면 동일하게 이용이 가능하다.
아마 추후에 지원버전을 높이는 시점에 SceneDelegate 부분을 좀 많이 건들이게 되지 않을까 싶다.
그러나 Deployment Target이 13이 되려면 앞으로 몇년은 더 걸릴 예정이기 때문에...
그냥 그렇구나 정도로만 생각하고 넘어가면 된다.