본문 바로가기

iOS/학습정리

iOS) Scene-Based Life-Cycle

애플 공식 문서 Managing Your App's Life Cycle를 기반으로 작성합니다.

Scene 기반 앱 생명주기

앱은 Foreground나 Background에 있을 때 시스템 알림에 응답하고 다른 중요한 시스템 관련 이벤트를 처리한다.

앱의 현재 상태에 따라 할 수 있는 것과 없는 것이 결정되는데, 예를 들어 foreground 앱은 사용자와 상호작용 하므로 CPU를 포함한 시스템 리소스에 대해 우선권을 갖는다. 반대로 background 앱은 화면 밖에 있기 때문에 가능한 적은 일을 하고 가급적 아무 일도 안해야 한다. 앱의 상태가 바뀜에 따라 그에 맞춰 동작을 조정해야 한다.

앱의 상태가 변하면 UIKit은 그에 맞는 delegate 객체의 메소드를 호출하여 알려준다.

UISceneDelegate

  • iOS 13을 포함한 이후 버전
  • scene 기반 앱에서의 life-cycle events에 응답

UIApplicationDelegate

  • iOS 12를 포함한 이전 버전
  • life-cycle events에 응답

Respond to Scene-Based Life-Cycle Events

scene을 지원하는 앱에서는 UIKit이 각 scene 마다 별도의 life-cycle event를 전달한다. scene은 기기에서 실행중인 앱 UI 인스턴스를 의미한다. 유저는 각 앱마다 다수의 scene을 만들고 scene마다 화면에 표시하거나 숨기도록 조정할 수 있다.

각 scene마다 고유의 life-cycle을 가지므로 각각은 서로 다른 실행 상태일 수 있다. 예를 들어 한 scene은 foreground에, 다른 scene은 background에 있을 수 있다.

scene의 상태 변화는 다음과 같다. 사용자나 시스템이 새로운 scene을 요청하면, UIKit이 새로운 scene을 만들고 unattached 상태로 보낸다. 유저가 요청한 scene은 화면에 나타나는 foreground로 빠르게 이동한다. 시스템이 요청한 scene은 주로 이벤트를 처리할 수 있는 background로 이동한다. 예를 들어 시스템은 위치 이벤트를 처리하기 위해 scene을 background에 런치할 수 있다. 사용자가 앱의 UI를 닫으면, UIKit은 관련 scene을 background 상태로 보내고 결국 suspended 상태가 된다. UIKit은 자원 회수를 위해 언제든지 background나 suspended 상태에 있는 scene의 연결을 끊고 해당 scene을 unattaced 상태로 돌릴 수 있다.

출처: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle

SceneDelegate

scene()

optional func scene(_ scene: UIScene, 
      willConnectTo session: UISceneSession, 
            options connectionOptions: UIScene.ConnectionOptions)
  • scene: 앱에 연결되는 scene 객체
  • session: scene의 구성에 대한 세부 사항을 포함하는 섹션 객체
  • options: scene 구성을 위한 추가 옵션

이 메소드는 유저 인터페이스 객체를 생성하거나 복구할 때 불린다.

유저나 앱이 새로운 유저 인터페이스 객체를 요청하면 UIKit은 그에 맞는 scene 객체를 생성하고 앱에 연결한다. 이 메소드를 통해 scene이 표시해야 할 데이터를 로드하는 등 필요한 것을 구성하고 제공된 scene(UIWindowScene)에 window(UIWindow)을 연결한다. 스토리보드를 사용하면 window 프로퍼티는 자동으로 초기화되고 scene에 연결된다.

 

sceneWillEnterForeground()

optional func sceneWillEnterForeground(_ scene: UIScene)

scene이 background에서 foreground로 바뀔 때 불린다.
이 메소드는 background로 들어갈 때 변경한 부분을 되돌릴 때 사용한다.

 

sceneDidBecomeActive()

optional func sceneDidBecomeActive(_ scene: UIScene)

scene이 inactive 상태에서 active 상태로 바뀔 때 불린다.
scene이 inactive 상태일 때 멈춰졌던 작업을 재시작하거나 아직 시작하지 않은 작업을 새로 시작할 때 사용한다.

 

sceneWillResignActive()

optional func sceneWillResignActive(_ scene: UIScene)

active 상태에서 inactive 상태로 바뀔 때 불린다.
보통 수신 전화와 같이 일시적인 인터럽트에 의해 발생한다. 유저 데이터를 보존하고 모든 주요 작업을 중지하여 앱을 조용한 상태로 만든다.

 

sceneDidEnterBackground()

optional func sceneDidEnterBackground(_ scene: UIScene)

foreground에서 background로 변화할 때 불린다.
메모리를 해제하고 앱이 보유한 공유 자원을 해제한다.

 

sceneDidDisconnect()

optional func sceneDidDisconnect(_ scene: UIScene)

scene이 메모리에서 제거되기 전에 최종적으로 정리하고자 할 때 사용한다. 예를 들어, 파일이나 공유 자원에 대한 참조를 해제하고 유저 정보를 저장하는데 사용한다.

사용자가 앱 스위처에서 scene을 종료하면 UIKit은 해당 scene에 대한 연결을 끊는다. 사용자가 다른 앱으로 스위치하더라도 자동으로 UIKit이 scene에 대한 연결을 끊지는 않는다. 그러나 다른 프로세스를 위한 메모리 확보를 위해 scene에 대한 연결을 끊기도 한다.

백그라운드 상테 도입에 따른 메모리 해제

이미지를 메모리에서 해제할 때 asset에서 가져온 named 이미지는 버릴 필요 없다. 유사하게 NSCache로 관리하는 객체는 해제할 필요 없다.

백그라운드에 들어갈 때 공유 시스템 자원을 가지고 있으면 안된다. 백그라운드로 전환된 후에도 계속 카메라나 공유 시스템 DB에 접근하면 시스템은 해당 자원을 해제하기 위해 앱을 종료시킨다.

Snapshot

앱이 백그라운드 상태에 들어가면, UIKit은 앱의 현재 유저 인터페이스에 대한 스냅샷을 찍는다. 시스템은 앱 스위처에서 해당 이미지를 보여준다. 또한 foreground 상태로 돌아올 때에도 일시적으로 해당 이미지를 보여준다.

앱의 UI는 비밀번호나 신용카드 번호와 같이 민감한 개인 정보를 포함해서는 안된다. 그러한 정보가 있으면 백그라운드 상태에 들어갈 때 뷰에서 지워야 한다.