Search
🎞️

Scene 기반 App LifeCycle (after iOS 13)

부제
카테고리
iOS
SwiftUI
UIKit
세부 카테고리
LifeCycle
Combine 카테고리
최종편집일
2022/09/20 08:13
작성중
관련된 포스팅
생성 일시
2022/07/16 14:51
태그

App Life Cycle

앱이 foreground 에 존재하느냐, background 에 존재하느냐에 따라서 앱이 할 수 있는 것과 할 수 없는 것이 결정됩니다
Foreground : 사용자의 이목을 끄는 앱이므로, 시스템 자원에 대한 우선권을 가짐.
Background : 가능한한 적은 양의 작업을 수행하거나 , 아무것도 하지 않는 편이 좋음.
시스템은 이렇게 앱의 상태에 따라서 앱에게 신호를 보내고, 이에 따른 동작을 관리하는 것이 바로 생명주기를 활용한 앱 프로그래밍이라고 할 수 있을 것 같습니다.
iOS 12 이전의 앱 들에 대해서는 UIApplicationDelegate 객체를 사용하여 life cycle 이벤트에 대응하면 됩니다.
iOS 13 부터는 UISceneDelegate 객체를 사용해서 UI 관련 life cycle 이벤트에 대응할 수 있으며,
scene 기능을 지원하도록 하면, iOS 13 이상의 환경에서 iOS 앱은 항상 scene delegate 를 사용합니다. iOS 12 이전에서는 시스템은 sceneDelegate 를 무시하고 항상 app delegate 를 사용합니다.

Scene 기반 life cycle 이벤트에 대응하는 법.

Scene 이란?

디바이스에서 실행되는 multiple 앱 UI 객체. (iOS 13 이후에 생긴 개념)
iOS 12 까지는 하나의 앱이 하나의 process와 하나의 user interface 객체와만 matching 되었었다. 이전처럼 하나의 process를 사용하긴 하지만 다수의 UI 객체나 scene session들을 가지게 되기 때문이다.
사용자는 하나의 앱 프로세스에 대해 여러개의 scene 을 사용할 수 있다.
각각의 Scene 은 별개의 life cycle 을 가진다.
Scene 기능은 선택적인 기능이다. 필요하면 Info.plist 파일에 묘사된 UIApplicationSceneManifest key 값에 대한 value를 수정하면 된다.

SceneDelegate 란?

iOS 13 부터,
AppDelegate는 Process Lifecycle 역할은 그대로 유지
UI와 관련된 그 어떠한 작업들에 대한 
AppDelegateUI Lifecycle 핸들링 역할은 SceneDelegate 에게 넘겨주었음.
변경사항은 아래와 같다.

Scene 기반 App State 들

Scene 전환을 다음의 작업들을 하는데 사용하면 좋습니다.
UIKit 이 scene 을 app 에 connect 할 때,초기 UI를 구성하고 scene 에 필요한 데이터를 불러오세요.
Foreground - active 상태로 전환시, UI 를 구성하고 사용자 상호작용을 준비하세요
Foreground - active 상태를 떠날시, 데이터를 저장하고 앱의 행동을 종료하세요
Background 상태로 전환시, 중요한 작업들을 완료하고, 메모리를 가능한 많이 반환하세요.
scene disconnection 시, Scene 에 공유된 자원을 해제하세요
추가적적으로 ,UIApplicationDelegate 를 사용해 앱의 실행에 반응할 수 있습니다.

Life Cycle Event 핸들링

iOS 12 이전

UIApplicationDelegate

iOS 13 이후

UISceneDelegate

Foreground 전환 핸들링

UIKit always uses scene delegate objects when they are available.

Foreground 전환 시 데이터 업데이트

앱 실행시, foreground 상태로 전환 전 inactive 상태에서 앱이 시작된다.
app 의 launch time 메서드를 사용해서 실행시 필요한 동작을 수행하면 된다.
UIKit 은 아래의 메서드들을 호출하면서 앱을 inactive 상태로 옮긴다.
아래 메서드들을 사용해서 앱 실행중
필요한 disk 자원이나, 데이터들을 네트워크로부터 불러오세요
iOS 12 이전
applicationWillEnterForeground(_:) 
iOS 13 이후
sceneWillEnterForeground(_:) 

Foreground 전환 시 사용자 인터페이스 구성 및 초기 작업

시스템은 UI 를 구현하기 직전에 앱을 즉시 active 상태로 옮긴다.
Activation 은 앱의 UI와 run time 행동을 구성하기에 좋은 타이밍!! 이 과정을 block 가능한 코드를 절대 실행해서는 안됨.
만약 데이터가 앱 밖에서도 자주 변경된다면,
background task 를 이용해서 네트워킹하는 것이 바람직함.
자주 변경되지 않는다면, 존재하는 데이터를 보여주면서 비동기적으로 변경사항을 불러오면된다.
앱의 윈도우 표시
현재 보여지는 뷰컨트롤러 변경
뷰와 컨트롤의 상태와 데이터 업데이트
게임의 일시정지를 재개하기 위한 컨트롤 표시
dispatch queue 의 재개.
데이터 소스 객체 업데이트
주기적인 작업을위한 타이머 시작
iOS 12 이전
applicationDidBecomeActive(_:)
iOS 13 이후
sceneDidBecomeActive(_:)

View 나타났을 때 UI 별 구체적인 작업을 시작

뷰 컨트롤러의 viewWillAppear() 메서드를 사용해서 앱 인터페이스의 마지막 업데이트를 수행할 수 있다.
UI 애니메이션 시작
미디어 파일 재생 시작
게임에 필요한 그래픽 표시.
뷰 컨트롤러가 화면에 나타나기 전에 인터페이스는 표시할 준비가 되어있어야 된다.

Background 전환 핸들링

백그라운드로 앱이 전환되는 이유에는 정말 여러가지가 있다.
사용자가 foreground 앱에서 나가는 경우
시스템이 앱을 바로 background 상태로 실행하는 경우
시스템이 suspend 된 앱을 background 로 옮기는 경우
앱이 백그라운드에 존재할 때는 가능한 일을 하지 말아야한다.
따라서 앱이 백그라운드로 전환시 작업을 중지하고 공유 자원을 해제하자!

비활성화에 따른 앱 종료

시스템은 많은 이유로 앱을 비활성화 한다
foreground 앱에서 나갈 때
시스템 경고 발생시
시스템 경고 패널이 dismiss 되면 시스템은 앱을 자동으로 재활성화
비활성화 단계에서 사용자의 데이터를 저장하고, 앱의 주요 작업을 일시정지하자!
비활성화 직전 UIKit 은 아래의 메서드를 호출한다.
iOS 12 이전
applicationWillResignActive()
iOS 13 이후
sceneWillResignActive()
아래의 작업들을 넣어두면 좋다.
사용자 데이터 파일에 저장
dispatch queue 실행 연기
새 작업 스케줄 중단
활성화된 타이머 종료
게임플레이 일시정지

백그라운드 전환에 따른 자원해제

백그라운드 전환시 앱이 홀딩하던 메모리와 공유된 자원들을 놓아주어야한다.
메모리 해제가 특히 중요!
Foreground 앱이 메모리에 대해 우선권을 갖으며,
시스템은 이에 필요한 메모리를 다른 background 앱들을 필요한 만큼 종료해서 메모리를 사용가능하도록 만듦.
백그라운드 진입전 모든 시스템 자원들을 해제 해야한다!!!!!
만약 해제 해주지 않으면 시스템은 백그라운드에서 시스템 자원을 보유중인 앱을 먼저 종료시킨다!
시스템 프레임워크를 사용중이라면 이러한 자원을 해제하는 방법을 반드시 프레임워크의 공식 문서의 가이드라인을 확인해 해제해야한다.
백그라운드 진입 직전 호출되는 메서드
iOS 12 이전
applicationDidEnterBackground()
iOS 13 이후
scenDidEnterBackground()
아래의 작업을 넣어두면 좋다
이미지 또는 미디어 폐기
disk 에서 다시 불러오기가 가능한 객체 폐기
카메라 및 다른 하드웨어 자원 접근 해제
임시 인터페이스 해제(예 : 경고창)
공유 시스템 데이터베이스와의 연결 해제
에셋에서 가져온 이미지를 폐기할 필요는 없다. 비슷하게 NSDiscardableContent 프로토콜을 채택한 객체들은 release 해줄 필요가 없다.
이러한 객체들은 시스템이 자동으로 객체를 청소해준다!!! (개꿀...)

백그라운드 전환에 따른 UI 스크린샷

요거 요거 재밌습니다.
앱이 백그라운드로 전환되고 delegate 메서드들이 실행이 종료된 후에 UIkit 은 앱의 현재 UI 를 캡쳐합니다. 이렇게 캡쳐된 UI 는 app switcher 에서 사용되는 거구요!
(여태껏 저는 이 앱들이 전부 그대로 실행중인 앱인줄 알고,,, 메모리 환경을 위해 주기적으로 밀어서 없애줬는데,,, 딱히 그럴필요가 없는 거였다니...)
아이패드 앱 스위쳐
이 과정에 있어서 중요한 점이 하나있습니다.
바로 민감한 사용자 정보같은 것들은 포함하면 안된다는 건데요.
앱전체를 블러처리할 수도 있지만.
중요한 정보가 포함되어 있는 UI 만 날려버리는 것이 훨씬 더 바람직해 보입니다.(app switcher 사용성을 위해)
백그라운드 전환 전에 민감한 정보를 View 에서 제거해야합니다.
추가적으로
경고 창, 임시 인터페이스, 시스템 뷰컨트롤러는 캡쳐시 앱 컨트롤러를 가리기 때문에 마찬가지로 백그라운드 전환시 이를 dismiss 해주세요!!
마찬가지로 민감한 정보를 View 에서 제거했다면 foreground 로 전환시에는 이를 되돌려 놓는 작업또한 구현을 해야겠네요!

백그라운드 상태에서 중요 이벤트에 반응하기

앱은 보통 백그라운드에 들어가면 별도의 실행시간을 못가져요
하지만 UIKit 은 아래의 기능들에 한에 실행 시간을 보장해주기도 합니다.
위치기반 서비스
에어 플레이를 사용하는 오디오 통신
IP 기반 음성통화
외부 악세서리와의 통신
블루투스 악세서리와의 통신
서버로부터의 규칙적인 업데이트
APN 서비스 지원
앱이 백그라운드 모드를 사용하고자 한다면 Xcode 에서 background feature 을 지원하도록 설정하시면 됩니다.