> **사용자 경험을 유지하고 앱의 성능을 최적하하기 위해 앱의 상태(e.g. foreground, background) 변화에 따라 수행할 작업을 이해하고 처리하자.** <br> ## 개요 iOS 앱의 상태(state) 변화에 따라 앱이 수행할 수 있는 작업과 할 수 없는 작업이 나뉜다. 예시 - **foreground** 상태: 화면에 표시되고 있는 상태로, CPU와 같은 리소스를 사용할 때 우선권을 가진다. - **background** 상태: 화면에서 벗어난 상태로, 최소한의 작업을 수행하거나 아예 아무 작업도 하지 않아야 한다. (리소스를 최소한으로 사용하는 것이 중요함) <br> 앱의 상태가 변할 때마다, UIKit은 적절한 delegate 객체의 메서드를 호출하여 해당 상태 변화에 대응할 수 있도록 한다. - **iOS 13 이후, scene-based 앱에서는 [[Scene과 UISceneDelegate|UISceneDelegate]] 객체를 사용하여 라이프사이클 이벤트에 대응한다.** - **iOS 12와 그 이전에는 [[AppDelegate와 UIApplicationDelegate|UIApplicationDelegate]] 객체를 사용하여 라이프사이클 이벤트에 대응한다.** <br> >만약 앱에서 scene support를 활성화했다면 iOS 13 이후에는 항상 scene delegates가 사용되며, iOS 12와 그 전에는 app delegate가 사용된다. <br><br> ## scene-based 라이프사이클에 대응하기 iOS 앱이 [[Scene과 UISceneDelegate|scene]]을 지원할 경우, **각 scene에 대한 별도의 라이프사이클 이벤트가 제공된다.** <span style="color:gray;">여기서 scene은 디바이스에서 실행 중인 앱의 UI의 하나의 인스턴스를 나타낸다. </span> 사용자는 각 앱에 대해 **여러 개의 scene**을 생성하고 따로따로 표시하거나 숨길 수 있다. 각 scene은 고유의 라이프사이클을 갖기 때문에 서로 다른 실행 상태에 있을 수 있다. 예를 들어, 한 scene이 foreground에 있을 때, 다른 scene들은 background에 있거나 일시 중지된 상태에 있을 수 있다. <br> >scene support는 앱에게 선택적인 기능(opt-in feature)이다. 이를 활성화하려면 앱의 `Info.plist` 에 `UIApplicationSceneManifest` 키를 추가해야 한다. <br><br> #### scene을 통한 상태 전환 ![[scene_based_life_cycle.png|center|400]] <br> - 새로운 scene이 앱에 대한 사용자 또는 시스템의 요청으로 생성되면, UIKit은 이를 **"unattached"** 상태로 만든다. - 사용자 요청에 의한 scene은 빠르게 foreground로 이동하여 화면에 나타난다. 반면 시스템 요청에 의한 scene은 일반적으로 이벤트를 처리하기 위해 background로 이동한다. <span style="color:gray;">예를 들어, 시스템은 위치와 관련된 이벤트를 처리하기 위해 background에서 scene을 시작할 수 있다.</span> - 사용자가 앱 UI를 닫으면 UIKit은 관련된 scene을 background 상태로 이동시키고, 나중에는 중단된(suspended) 상태로 전환한다. > **UIKit은 언제든지 background에 있거나 중단된 scene을 연결 해제하여 리소스를 회수할 수 있으며, 이렇게 되면 해당 scene은 "unattached" 상태로 돌아간다.** <br><br> #### scene 전환 때 수행할 작업 ✨ - **scene이 앱에 연결될 때** 초기 UI를 구성하고 scene이 필요로 하는 데이터를 로드한다. - **foreground-active 상태로 전환될 때** UI를 구성하고 사용자와 상호작용하기 위해 준비한다. - **foreground-active 상태에서 빠져나갈 때** 데이터를 저장하고 앱의 활동을 최소화한다. - **background 상태로 전환될 때** 중요한 작업을 완료하고 최대한의 메모리를 해제하며 app snapshot을 준비한다. - **scene이 연결 해제될 때**, scene과 관련된 공유 리소스를 정리한다. - scene과 관련된 이벤트뿐만 아니라, **앱이 시작될 때** `UIApplicationDelegate` 객체를 사용하여 앱의 실행에 응답해야 한다. - [Responding to the launch of your app](https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app) 참조하기 <br> > **app snapshot** > 사용자가 앱을 종료하거나 다른 앱으로 전환할 때 앱의 현재 상태와 UI의 이미지를 저장하는 개념. > 이를 통해 사용자가 다시 앱을 열 때 앱이 마지막으로 종료되었을 때와 같은 상태로 빠르게 복원될 수 있다. <br><br> ## app-based 라이프사이클에 대응하기 **iOS 12 및 그 이전 버전, 그리고 scene을 지원하지 않은 앱에서는 모든 라이프사이클 이벤트가 UIKit에 의해 `UIApplicationDelegate` 객체로 전달된다.** app delegate는 앱의 모든 window를 관리하며, 여기에는 별도의 화면에 표시되는 window도 포함된다. 따라서 앱 상태 전환은 앱의 전체 UI에 영향을 미치며, 외부 디스플레이에 표시된 내용도 포함된다. <br><br> #### app delegate를 통한 상태 전환 ![[app_based_life_cycle.png|center|400]] <br> - 시스템은 앱을 실행한 후, UI가 화면에 나타나기 전에 앱을 inactive 또는 background 상태로 둔다. - foreground로 실행되면 시스템은 자동으로 앱을 active 상태로 전환한다. 그 이후에는 앱이 종료될 때까지 active와 background 상태 간을 오가게 된다. <br><br> #### app 전환 때 수행할 작업 - **앱 런치 시,** 앱의 데이터 구조 및 UI를 초기화한다. - **active 상태로 전환될 때**, UI를 설정하고 사용자와 상호작용하기 위해 준비한다. - **inactive 상태로 전환될 때**, 데이터를 저장하고 앱의 활동을 최소화한다. - **background 상태로 전환될 때**, 중요한 작업을 완료하고 최대한의 메모리를 해제하며 app snapshot을 준비한다. - **앱 종료 시**, 즉시 모든 작업을 중단하고 모든 공유 리소스를 해제한다. - [[AppDelegate와 UIApplicationDelegate#^036e79|applicationWillTerminate(_:)]] 참조하기 <br> <br> ## 라이프사이클 이벤트 이외의 중요한 이벤트 iOS 앱은 라이프사이클 이벤트 이외에도 다양한 중요한 이벤트에 대응할 수 있어야 한다. 이러한 이벤트들은 `UIApplicationDelegate` 객체를 통해 처리될 수 있으며, 때로는 알림(notifications)을 사용하여 앱의 다른 부분에서도 처리할 수 있다. 1. **Memory warnings:** - 앱의 메모리 사용량이 너무 높을 때 발생하는 이벤트. 메모리 사용을 줄이는 등의 조치를 취해야 한다. - [[AppDelegate와 UIApplicationDelegate#^89e449|applicationDidReceiveMemoryWarning(_:)]] 메서드 사용 - [Responding to memory warnings](https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle/responding_to_memory_warnings) 참조하기 2. **Protected data becomes available/unavailable:** - 사용자가 디바이스를 잠금 또는 잠금 해제할 때 발생하는 이벤트 - `applicationProtectedDataDidBecomeAvailable(_:)` 및 `applicationProtectedDataWillBecomeUnavailable(_:)` 메서드 사용 3. **Handoff tasks:** - `NSUserActivity` 객체를 처리해야 할 때 발생하는 이벤트. - `application(_:didUpdate:)` 메서드 사용 4. **Time changes:** - 전화 통신사가 시간 업데이트를 보낼 때와 같은 여러 시간 변경 이벤트에 대한 처리. - `applicationSignificantTimeChange(_:)` 메서드 사용 5. **Open URLs:** - 앱이 리소스를 열어야 할 때 발생하는 이벤트. - `application(_:open:options:)` 메서드 사용 <br> <br> <br> --- **참고 문서** https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle **추천 링크** [Preparing your UI to run in the foreground](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_foreground) [ Preparing your UI to run in the background](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background) <br> <br> <br> <br>