
이번 학습부터는 iOS의 여러가지 생명 주기를 학습해보자.
처음은 가장 큰 생명주기인 Scene과 App의 생명주기에 해당되는 단계와그 단계에
포함되는 콜백함수들을 짝지어 학습해보자.
App Life Cycle
iOS 12 이하 버전에서는 scene을 지원하지 않기 때문에 UIkit의 모든 life-cycle 관련 이벤트들은
UIApplicationDelegate 객체에서 처리한다.

1. Not Running
앱이 실행되지 않았거나 완전히 종료되어 동작하지 않는 상태
// 앱 최초로 실행할 코드 작성
// 앱 실행 준비가 끝가지 직전에 호출
// main storyboard 또는 nib 파일이 로드된 후
// 실행된 후 InActive 상태가 된다.
func application(
_ application: UIApplication,
willFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool
// 사용자에게 보여주기 직전에 호출됨
// 주로 초기화 코드가 사용 됨
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool
// 앱이 메모리에서 완전히 종료 및 제거
// 용자 데이터 저장 및 타이머 무효화와 같은 앱에 대한 최종 정리 작업을 수행해야 한다.
func applicationWillTerminate(_ application: UIApplication)
여기서 위에 두 함수의 리턴값 Bool은 무슨 의미일까?
기본은 true이다.
false로 바꿔도 앱은 정상적으로 실행되며, 아무 문제 없다.
return 값은 앱이 URL ( App Scheme ) 으로 실행된 경우 유효하다.
URL로 실행 된 경우 launchOptions에 URL이 넘어오며 return을 false로 하면 openURL로 url을 오픈하지 않고 넘어간다.
딥링크 기능이 안되나는 의미로 추측된다.
2. In - Active
앱이 Foreground에서 실행 중이지만 이벤트는 받지 못하는 상태.
Active 상태로 넘어가기 전에 앱은 반드시 이 상태를 거친다.
// InActive 상태에서 Active 상태로 이동했음을 알리기 위해 이 메서드를 호출한다.
func applicationDidBecomeActive(_ application: UIApplication)
// delegate에게 앱이 Background 상태에 있음을 알린다.
// 앱이 Background에 있을 때는 가능한 적은 일을 수행해야하며, 가급적이면 아무 작업도 수행하지 않는 것이 좋다.
func applicationDidEnterBackground(_ application: UIApplication)
3 Active ( Foreground )
앱이 실행 중이고 이벤트를 받을 수 있는 상태
//UIKit은 앱이 Active상태에서 InActive 상태로 이동한다는 것을 알리기 위해 이 메서드를 호출한다.
// 앱을 Background 상태로 전환하기 시작할 때나
// 수신 전화나 SMS 메시지와 같은 일시적인 interruption 으로 인해 InActive 상태로 전환될 수 있다.
func applicationWillResignActive(_ application: UIApplication)
4. Background
앱 사용중에 다른 앱을 실행하거나 홈 화면으로 나갔을 때 상태. 백그라운드에서 동작하는
코드를 추가하면 suspended 상태로 넘어가지 않고 백그라운드 상태를 유지
// 앱이 Background 에서 Foreground로 진입할 것임을 delegate에게 알린다.
// 앱이 Background 상태던 앱이 InActive 상태로 전환된다.
func applicationWillEnterForeground(_ application: UIApplication)
5. Suspended
앱이 background 상태에서 추가적인 작업을 하지 않으면 곧바로 suspended 상태로 진입.
시스템에 의해 자동으로 suspended 상태로 되기 때문에, 상태 이동에 대한 알림을 따로 받지 않음
Scene Life Cycle
iOS 13을 기점으로 Multiple Window를 지원하기 위해 Scene이라는 개념이 생겼다.
Scene을 지원하는 App의 경우 Life cycle 노티를 수신하는 delegate가 AppDelegate가 아닌 SceneDelegate가 된다.
정리하면, iOS 12까지는 항상 AppDelegate가 수신하고, iOS 13부터는 Info.plist에서
Scene configuration을 제공하는지 여부에 따라 AppDelegate 혹은 SceneDelegate가 수신한다.

1. Unattached
scene은 만들어졌으나 아직 App에 연결되지 않은 상태
// App Delegate에서 Scene Session에 대한 Configuration이 끝나면
// Scene Session이 생성되면서 이 메서드를 호출한다.
// 이 메서드에서 UIWindowScene을 등록하는 과정을 거치게 된다.
// delegate에게 앱에 scene이 추가되었다는 것을 알려주는 역할
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
)
2. Foreground-In-Active
현재 UI에 보이는 상태이나 event를 수신할 수 없는 상태
// scene이 inactive 상태에서 active 상태로 전환되었을 때에 호출되는 메서드다.
func sceneDidBecomeActive(_ scene: UIScene)
// 앱을 나간 후 willResignActive메서드 다음에 호출되는 메서드입니다.
// 이후에는 didDisconnect 메서드가 호출됩니다.
// delegate에게 scene이 background에서 돌아가고(running) 있고
// 더이상 onscreen상태가 아니라는 것을 알려주는 메서드이다.
func sceneDidEnterBackground(_ scene: UIScene)
3. Foreground-Active
현재 UI에 보이는 상태이며 event를 수신가능한 상태
// Scene이 active상태에서 inactive상태로 전환될 때 호출하는 메서드다.
// 대표적인 경우로, 앱을 사용하는 도중에 alert가 오거나, 전화가 오는 등의 인터럽트가 발생하면 호출되는 메서드
func sceneWillResignActive(_ scene: UIScene)
4. Background
현재 UI에 보이지 않는 상태
// scene이 background에서 foreground로 이동할 때 호출되는 메서드다.
// 즉, delegate에게 scene이 foreground에서 시작될 것이고
// user에게 보여질 것 이라는 것을 말해주는 역할을 가지고 있다.
func sceneWillEnterForeground(_ scene: UIScene)
5. Suspend
Background에 있다가 특별한 작업을 하지 않는 경우 suspend로 전환
정리
AppDelegate.swift
//
// AppDelegate.swift
// Playground
//
// Created by yongbeomkwak on 9/1/24.
//
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// 앱이 처음 시작될 때 호출됩니다. 앱 초기화, 설정 로드, 초기 상태 설정 등을 처리합니다.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print(#function)
return true
}
// MARK: UISceneSession Lifecycle
// 새로운 SceneSession이 생성될 때 호출됩니다.
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
print(#function)
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
// 사용자가 SceneSession을 닫았을 때 호출됩니다.
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
print(#function)
}
// MARK: Application State Transitions
// 앱이 활성화될 때 호출됩니다. (앱이 백그라운드에서 포그라운드로 전환될 때 포함)
func applicationDidBecomeActive(_ application: UIApplication) {
print(#function)
}
// 앱이 비활성화 상태로 전환되기 전에 호출됩니다. (예: 전화가 오거나 알림이 표시될 때)
func applicationWillResignActive(_ application: UIApplication) {
print(#function)
}
// 앱이 백그라운드로 진입할 때 호출됩니다.
func applicationDidEnterBackground(_ application: UIApplication) {
print(#function)
}
// 앱이 백그라운드에서 포그라운드로 전환될 때 호출됩니다.
func applicationWillEnterForeground(_ application: UIApplication) {
print(#function)
}
// 앱이 종료되기 전에 호출됩니다.
func applicationWillTerminate(_ application: UIApplication) {
print(#function)
}
}
SceneDelegate.swift
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
// MARK: Scene Lifecycle
// Scene이 생성되고 연결될 때 호출됩니다. 초기화 및 초기 화면 설정을 처리합니다.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let vc = ViewController()
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
// Scene이 활성화될 때 호출됩니다. (앱이 백그라운드에서 포그라운드로 전환될 때 포함)
func sceneDidBecomeActive(_ scene: UIScene) {
print(#function)
}
// Scene이 비활성화 상태로 전환되기 전에 호출됩니다.
func sceneWillResignActive(_ scene: UIScene) {
print(#function)
}
// Scene이 백그라운드에서 포그라운드로 전환될 때 호출됩니다.
func sceneWillEnterForeground(_ scene: UIScene) {
print(#function)
}
// Scene이 백그라운드로 진입할 때 호출됩니다.
func sceneDidEnterBackground(_ scene: UIScene) {
print(#function)
}
// Scene이 시스템에 의해 해제될 때 호출됩니다.
func sceneDidDisconnect(_ scene: UIScene) {
print(#function)
}
}
실제 테스트 (without Scene)
앱 진입 -> 다른 앱 노티 -> 다른앱으로 이동 -> 앱 복귀

앱 스위치 본후 -> 복귀

앱 스위치에서 강제종료

실제 테스트 (with Scene)
앱 진입 -> 다른 앱 노티 -> 다른앱으로 이동 -> 앱 복귀

앱 스위치 후 -> 복귀

앱 스위치에서 강제종료

참고
[IOS] 어플리케이션의 생명 주기 - Life Cycle of Application
Devlog 와 TIL 입니다. 개발을 하면서 알게된 내용을 다루고 있습니다.
dev200ok.blogspot.com
'iOS > UIKit' 카테고리의 다른 글
생명주기 (4) [ 업데이트 Cycle ] (2) | 2024.09.01 |
---|---|
생명주기 (3) [ View 생명주기 ] (0) | 2024.09.01 |
UIKit 코드 베이스 셋팅 (0) | 2024.09.01 |
생명주기 (2) [ ViewController 생명주기 ] (0) | 2024.08.31 |
UIResponder Chain (1) | 2024.08.30 |