💡 AppDelegate, SceneDelegate 클래스의 역할이 무엇인지 알아봅니다.
C 기반 프로그램이 그렇듯 iOS 앱 또한 main
함수의 시작으로 Application Life Cycle이 시작됩니다.
main function is the entry point.
하지만 Xcode에서 App 프로젝트를 생성하면 main
함수가 보이지 않는데, 대신 @UIApplicationMain attribute가 메인 함수와 같은 역할을 합니다(@main으로 최근 변경됨).
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//
}
@UIApplicationMain은 AppDelegate.swift 파일의 AppDelegate class 선언부 위에서 볼 수 있으며, 다음과 같은 일을 합니다.
UIApplication
The centralized point of control and coordination for apps running in iOS.
메인 함수가 생성하는 UIApplication은 실행 중인 app의 중앙 처리 지점(point) 입니다.
메인 함수는 이 객체를 singleton으로 생성하므로 shared로 전역에서 접근할 수 있습니다.
따라서, 하나의 app은 하나의 UIApplication 인스턴스를 갖게 됩니다.
application object은
user event에 대한 초기 routing을 처리(handle)하거나,
= user event가 발생하면 해당 UIControl 객체(UIButton..)에 전달하는 일
런타임 이벤트 — app launch, low-memory warnings, and app termination — 를 delegate에게 알리고 그에 따라 반응할 수 있도록 합니다.
메인 함수는 AppDelegate의 인스턴스도 생성하는데, AppDelegate은 UIApplicationDelegate protocol을 채택하고 있습니다.
application object의 대리자(delegate) 역할을 수행합니다.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
위 AppDelegate의 application(_:didFinishLaunchingWithOptions:)
은 true
만을 리턴하고 그외 아무 기능도 하지 않는데,
rootViewController를 설정하는 코드 등을 작성할 수도 있습니다.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let timeline = TimelineViewController()
let navigation = UINavigationController(rootViewController: timeline)
let frame = UIScreen.main.bounds
window = UIWindow(frame: frame)
window!.rootViewController = navigation
window!.makeKeyAndVisible()
return true
}
SceneDelegate.swift 파일은 iOS 13부터 새로 추가된 것으로, 기존 AppDelegate가 하던 일의 일부를 SceneDelegate가 하도록 변경되었습니다.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
SceneDelegate class는 UIWindowSceneDelegate protocol을 채택하고 있는데, UIWindowSceneDelegate은 UISceneDelegate protocol의 subclass입니다(상속 관계).
Protocol UISceneDelegate
The core methods you use to respond to life-cycle events occurring within a scene.
UISceneDelegate protocol은 scene 내에서 일어나는 life cycle event에 대한 메서드가 정의되어 있습니다.
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
iOS 13부터 AppDelegate의 기능의 일부가 SceneDelegate로 나뉜 이유는 app이 multi-window를 지원하기 때문인데, 이에 따라 scene 간의 동기화를 위해 UISceneSession의 개념이 AppDelegate에 추가되었습니다.
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}