티스토리 뷰
Life Cycle(생명 주기), 즉 실행부터 종료까지의 주기
Launch Sequence
About the App Launch Sequence - Apple Developer Documentation
앱이 실행되는 과정은 아래의 그림으로 나타낼 수 있다.
- 앱이 유저 혹은 시스템에 의해서 실행된다
- 프로그램의 시작점인 main() 함수에 의해 UIKit의 UIApplicationMain(_:_:_:_:) 메소드가 호출된다
- UIApplicationMain(_:_:_:_:) 메소드를 통해 UIApplication 싱글톤 객체와 AppDelegate 객체가 생성된다. 또한 main storyboard 혹은 nib file의 기본 인터페이스를 로드하고 초기 세팅값(info.plist)을 불러오고 앱을 Main Run Loop에 올려서 이벤트 처리를 시작하도록 한다.
- UIKit이 AppDelegate의 application(_:willFinishLaunchingWithOptions:) 메소드를 호출한다
- UIKit이 state 복구 과정을 수행한다.
- UIKit이 AppDelegate의 application(_:didFinishLaunchingWithOptions:) 메소드를 호출한다]
이렇게 실행 초기화 과정이 끝나면 시스템이 UI를 보여주고 생명주기를 관리하기 위해 SceneDelegate 혹은 AppDelegate를 이용하게 된다.
위 과정에서 UIApplication 객체와 AppDelegate 객체가 생성되는 과정을 좀 더 들여다 보자면,,
iOS 앱은 C 기반 프로그램이고 모든 C언어 기반 프로그램의 시작점은 main() 메소드이다.
iOS 앱 프로젝트를 생성할때 언어를 Swift로 설정하여 생성하면 AppDelgate.swift의 @main annotation을 통해 앱 진입점이 설정되어 있어서 따로 잡아주지 않아도 된다.
(Xcode 12버전부터 main annotation이 @main 으로 바뀌었다. 그전에는 @UIApplicationMain 이었다. Xcode 11에서 @main 하면 아마 오류뜸.)
Objective-C로 설정하여 프로젝트를 만들면 main.m 파일에서 바로 그 main() 메소드를 확인할 수 있다.
이렇게 UIApplicationMain() 메소드를 호출하는 것을 확인할 수 있다.
Swift 기반 프로젝트에서도 굳이굳이 해보자면 해볼 수 있다.
이렇게 하면 AppDelegate에 @main annotation이 없어도 main.swift(이때 이름은 무조건 main.swift 여야함..) 파일을 추가해서 UIApplicationMain() 메소드를 UIApplicationDelegate 클래스를 지정해서 명시적으로 호출하면 잘 실행이 된다. 근데 대부분의 앱의 경우 main 메소드를 건드릴 일이 없다고 한다.
여기서 main 메소드를 건드려야 할 경우가 어떤 경우냐면,,,
UIApplicationMain() 메소드의 3번째 인자로 String 타입의 UIApplication 클래스 혹은 서브클래스의 이름을 받을 수 있는데, 바로 이 경우, UIApplication을 서브클래싱 해야하는 경우에만,, 가능하면 안하면 좋겠지만~ 굳이굳이 해야한다면~ 이 경우에만,,
그럼 굳이굳이 이 UIApplication을 서브클래싱 해야하는 경우가 도대체 언제인가??
설명에 나와있듯이 앱에 들어오는 이벤트를 시스템이 처리하기 전에 직접 처리해야 하는 경우에 UIApplication을 서브클래싱 후 sendEvent() 혹은 sendAction() 을 재정의 하면 된다. 그리고 super.sendEvent() 로 시스템한테 꼭 되돌려줘야 한다~ 라고 신신당부를 합니다..
이렇게까지 이벤트를 인터셉트해서 뭔가를 하는 앱이 내가 사용하는 앱 중에 있을까? 곰곰히 생각해봐도 적절한 예시가 안떠오름,,,
아무튼!! 여기까지 앱의 실행 과정 자체를 살펴보았고,, 이제 앱의 상태 변화를 보자면,,
App State
UIApplicationDelegate(AppDelegate)를 이용해서 앱 상태 변화에 따라 응답할 수 있는데, iOS 13 부터 UISceneDelegate를 이용한 scene 기반 앱에서는 각 Scene 별로 다른 상태 변화에 응답할 수 있다.
- Respond to App-Based Life-Cycle Events
- Respond to Scene-Based Life-Cycle Events
위 그림처럼, iOS 앱의 상태는 5가지로 볼 수 있다.
- Not Running
- 아무것도 실행하지 않은 상태
- Inactive
- 앱이 Foreground 상태로 돌아가지만 이벤트는 받지 않는 상태,, 상태 전환 과정에서 잠깐 머무는 단계
- Active와 Background 사이의 전환일 때 잠깐 Inactive 상태가 된다. 예를 들어 시스템이 앱 앞쪽으로 Alert를 보여줄때(다른 앱에서의 푸시를 보여줄때를 말하는 것 같은데 잘 모르곘음.), 그리고 Application Switcher를 보여줄때(홈버튼 두번탭하면 나오는 그거인듯) 등
- Active
- 앱이 Foreground에서 돌아가고 있는 일반적인 상태
- Background
- 앱이 Suspended(유예) 상태로 진입하기 전에 거치는 상태
- Suspended
- 앱이 Background 상태에 있지만, 아무 코드도 실행하지 않는 상태, 시스템이 임의로 Background 상태의 앱을 Suspended 상태로 만듦
AppDelegate 혹은 SceneDelegate의 아래 메소드들을 이용해서 앱의 상태가 변할 때 수행할 작업들을 설정할 수 있다.
참고 🔍
https://medium.com/@neroxiao/ios-app-life-cycle-ec1b31cee9dc
https://hcn1519.github.io/articles/2017-09/ios_app_lifeCycle
https://zeddios.tistory.com/539
https://qiita.com/KenNagami/items/cbbe98b736fbdb24fef8
https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
https://developer.apple.com/documentation/uikit/1622933-uiapplicationmain
https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence
'iOS' 카테고리의 다른 글
[번역] WatchKit (0) | 2022.01.20 |
---|---|
iOS status bar style 변경하기 (1) | 2021.11.18 |
Bastard Injection (0) | 2021.08.17 |
iOS TextField memory leak (0) | 2021.07.16 |
swift static, class, final class (0) | 2020.08.02 |
- Total
- Today
- Yesterday
- opentutorial
- split view controller
- 에피쿠로스
- spm
- strings.xml
- StatusBar
- 읏샷샤 화이팅 앗샷샤 화이팅
- UISplitViewController
- 스토아학파
- 생활코딩
- lldb
- 프론트엔드 공부
- watchOS
- watchKit
- 냉철
- Xcode
- iOS App Life Cycle
- statusBarStyle
- Localizable
- iPadOS
- 에피큐어
- ios
- 철학의 역사
- 클론코딩
- iPad
- SplitViewController
- watchOS life cycle
- private repository
- Android
- bitbucket
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |