ApplicationDelegate, SceneDelegate

우선 앱 시작 시퀸스는 다음과 같다.

1. Xcode에서 제공하는 main 함수를 시스템이 호출

2. main함수는 UIApplication과 app delegate를 생성하는 함수 UIApplicationMain()을 호출

3. UIKit은 Info.plist 혹은 Xcode의 타겟에서 지정한 기본 스토리보드를 로드함. 만약 스토리보드를 사용하지 않을 시 이 단계를 건너 뜀.

4. UIKit이 app delegate에서 application(_: willFinishLaunchingWithOptions:)를 호출

5. UIKit이 UI restoration process을 수행함. application(_:shouldRestoreApplicationState:)의 값이 true경우 수행하고, false일 경우 수행 안함. UI restoration process의 내용은 여기서 다루지 않을것임.

6. UIKit이 app delegate의 application(_: didFinishLaunchingWithOptions:)을 호출

 

시작 시퀸스가 완료되면 시스템은 app delegate 또는 scene delegate를 사용하여 앱의 사용자 인터페이스를 표시하고, 앱의 라이프 사이클을 관리함.

 

UIApplicationDelegate

앱의 shared behavior을 관리한다. 시스템과 일부 상호 작용을 하기 위해 UIApplication과 함께 작동한다. UIApplication을 이용해 아래와 같은것들을 처리 할 수 있다.

  • 앱의 중심이 되는 데이터 구조 초기화
  • Scene 설정
  • 메모리 부족 경고, 다운로드 완료 등 외부에서 발생하는 알림에 응답
  • 앱 자체를 타겟으로 하는 이벤트 응답
  • 앱 실행시 필요한 서비스 등록

iOS 12버전 이하일때는 UI 라이프 사이클도 관리 했지만, iOS 13이상의 버전에서는 SceneDelegate가 관리하게 됬다. UI라이프 사이클을 관리 안하는거지, 앱이 실행되고 종료되는 것 같은 프로세스 라이프 사이클은 관리 한다.

이미지에 나와있는 것처럼 UI는 iOS 13 이후로 SceneDelegate가 책임을 가지게 됨.

또한 AppDelegate는 SceneSession이 생성되거나 기존 SceneSession이 삭제 될 때 시스템에서 AppDelegate에 알림.

 

앱을 누르고 나서 화면이 나타날때까지의 프로세스

화면에서 앱을 누르고나서, 화면이 나타나기 전에는 Appdelegate에서 앱 실행 시퀸스를 실행함. application(_: didFinishLaunchingWithOptions:)이 호출되고 난 후, 시스템은 Scene Session을 생성함.

 

이때 Scene을 생성하기 전에 UISceneConfiguration을 요청함. 

Configuration에는 어떤 SceneDelegate, 어떤 스토리보드를 사용할 것인지, Scene을 만들려고 하는 Scene의 서브클래스(지정한 경우)를 지정함.

프로젝트를 처음 만들고 info.plist를 보면 실제로 어떤 SceneDelegate를 사용할지, 어떤 스토리보드를 사용할지, Configuration Name이 기본적으로 설정된것을 볼 수 있음. 이렇게 SceneConfiguration을 이용해 어떤 Scene을 만들지 지정할 수 있음.

이 단계를 거치면 SceneSession은 만들어진 하나의 Scene을 추적(본문에는 track)하게 됨. 

 

한가지 유의할 점은 이 메소드는 새 Scene이나 window가 필요로 할때마다 호출됨. 앱 실행시 호출되는게 아님. 

 

이 단계가 끝나면 앱이 실행이 되지만, 아직 UI가 표시 되지 않는 상태.

왜냐하면 아직 Scene에서 window를 초기화 하지 않고 보일지 안보일지 정하지 않았기 때문임. 따라서 여기서 window를 초기화 하고, 윈도우를 보일지 말지 하는 작업을 진행 함. 그래서 스토리보드 말고 코드 베이스를 이용해 프로젝트를 할 때 보통 이런식으로 코드를 짜는것임.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      guard let windowScene = (scene as? UIWindowScene) else { return }
	window = UIWindow(windowScene: windowScene)
	let mainViewController = ViewController()
	window?.rootViewController = mainViewController
	window?.makeKeyAndVisible()
        
    }

 

참고:

https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app/about_the_app_launch_sequence#3894431

https://developer.apple.com/videos/play/wwdc2019/258/