티스토리 뷰

* 해당 글에는 개인 견해가 들어가있으므로 이곳을 참고하시면 조금 더 깔끔한 설명을 보실수도(?) 있습니다.

 

이 글은 SceneDelegate과 AppDelegate의 역할에 대해 다루겠습니다. 공식문서DW 블로그 및 프로젝트 경험을 바탕으로 정리하는 글이라 오류가 있을 수 있습니다. 오류 발견 시 댓글로 꼭 말씀해주세요! 시작해볼까요?

 

제가 약 5개월 전에 처음 iOS개발을 시작했을 땐 XCode 버전도 11 이상이었고 당시 보편적이었던 iOS 버전도 13이상이었습니다. 즉 제가 처음 배울 때도 Create New Project를 하면 AppDelegate.swift와 SceneDelegate이 있었습니다. 그래서 AppDelegate이 App Life-Cycle도 관리하던 호랭이 담배피던 시절(이 아니고 iOS 12 이하버전) 글들은 지금의 AppDelegate, SceneDelegate을 완전히 설명하진 못합니다. 그래서 저도 다시 정리할 겸 쓰게 되었습니다.

AppDelegate

// developer.apple.com

In iOS 12 and earlier, you use your app delegate to manage 
major life cycle events in your app. 

iOS 13 이전에는 AppDelegate가 app의 launch, foregrounding, backgrounding 등 App Life-Cycle을 관리하는 책임을 갖고 있었습니다. 그러나 iOS 13부터는 일부 역할을 SceneDelegate에게 넘겨주었습니다. 그러면 현재의 AppDelegate 역할을 무엇일까요?

Main Point of Entry

AppDelegate은 iOS 버전에 무관하게 application의 entry point 역할과 application level의 life-cycle을 관리하는 역할을 합니다. Apple은 AppDelegate.swift에 기본적으로 중요하다고 여기는 3개의 method들을 구현해 놓았습니다. 설명이 주석으로 매우 잘 적혀있긴 하지만 간단히 살펴보도록 합시다.

 

1. func application(_: didFinishLaunchingWithOptions: ) -> Bool

application의 setup을 이 메소드 안에서 진행하게 됩니다. iOS 12 이하 버전은 multiple window를 지원하지 않았어서 UIWindow 객체에 대한 configuration도 진행했었는데 이제는 multiple window를 지원하기 때문에 하나의 window 객체만 관리하는게 말이 되지 않죠.

 

2. func application(_: configurationForConnecting:options: ) -> UISceneConfiguration

application이 새로운 scene/window를 제공하려고 할 때 불리는 메소드입니다. (최초 launch 때 불리는 메소드 아님)

 

3. func application(_: didDiscardSceneSessions: )

사용자가 scene을 버릴 때 불립니다. 버리는 상황이려면 swipe로 multitasking windwo를 없앤다던지, 코드로서 없애는 경우가 있습니다. 

기타 역할

  • URL 열기
  • memory warning  wkqrl
  • 언제 종료(terminate) 될 지 잡기 등

Info.plist

프로젝트를 하다 보면 다양한 설정을 하기 위해 plist를 수정하게 됩니다. 카메라 액세스 요청을 한다던지, 마이크 요청을 한다던지 말이죠. 그런데 저는 최근에 Storyboard 없이 코드로만 View를 만들 때 plist를 만진 경험이 있습니다.

첫번째 사진은 plist를 캡쳐한 것이고 두번째 사진은 Project target의 deployment info를 캡쳐한 것입니다. plist를 보면 배열로 구성되어 있는 Application Session Role에 Storyboard Name = Main 으로 들어가있는 것 보이시죠? 그리고 밑에 Deployment info에도 Main Interface가 Main으로 되어있습니다. Main.storyboard 파일명을 뜻하는 것인데요, Storyboard를 쓰지 않고 코드를 짤 경우 저 두개를 지워줘야 합니다. 자 그러면, 어떤 화면을 보여주어야 하는지를 모르는 상태가 된 것 입니다. 어떤 화면이 entry point가 될지 알려줘야 합니다. 이 작업은 SceneDelegate에서 이뤄지게 되는데 SceneDelegate이 screen / window를 관리하는 책임을 지고 있기 때문입니다.

SceneDelegate

간단히 말해서 SceneDelegate은 화면에 무엇(scene/window)을 보여줄지 관리하는 역할을 합니다. Apple이 기본적으로 제공해주는 메소드와 주석을 통해 조금 더 알아보겠습니다.

 

1. scene(_: willConnectTo: options: )

UISceneSession lifecycle에서 제일 처음 불리는 메소드로 첫 content view, 새로운 UIWindow를 생성하고 window의 rootViewController를 설정합니다. 이 때 헷갈리지 말아야 할 것은 'window'가 사용자가 보는 window가 아니라 app이 작동하는 viewport를 나타낸다는 것이죠. 첫 view를 만드는데 쓰이기도 하지만 과거에 disconnected 된 UI를 되돌릴 때도 쓰기도 합니다. 

 

좀 전에 위에서 Main.storyboard를 없애서 어떤 화면을 보여줄지 모른다고 했죠? 이 곳에서 setup 하면 됩니다.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

   var window: UIWindow?
   
   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      guard let windowScene = (scene as? UIWindowScene) else { return }
      winodw = UIWindow(frame: windowScene.coordinateSpace.bounds)
      window?.windowScene = windowScene
      window?.rootViewController = NameOfRootViewController()
      window?.makeKeyAndVisible()
   }

}

 

2. sceneWillEnterForeground(_ :)

위 과정이 끝나면 sceneWillEnterForeground가 불리게 되는데 scene이 foreground로 전환될 때 불리는 데 두가지 경우가 있겠죠? 1) background → foreground 가 되었을 때 2) 그냥 처음 active 상태가 되었을 때

 

3. sceneDidBecomeActive(_ :)

다음으로 불리는 메소드는 sceneDidBecomeActive(_ :)로 scene이 setup 되고 화면에 보여지면서 사용 될 준비가 완료 된 상태입니다. inactive → active로 전환 될 때도 불리겠죠. 그래서 inactive상태가 되면서 멈춘 task를 재실행할 수도 있고 만약 처음 불렸다면 사용 준비가 완료되었으니 사용하면 됩니다.

 

4. sceneWillResignActive(_ :)

active한 상태에서 inactive 상태로 빠질 때 불리는데 사용 중 전화가 걸려오는 것 처럼 임시 interruption 때문에 발생할 수 있습니다.

 

5. sceneDidEnterBackground(_ :)

scene이 foreground에서 background로 전환 될 때 불리게 되므로 다음에 다시 foreground에 돌아 올 때 복원할 수 있도록 state 정보를 저장하거나, 데이터를 저장, 공유 자원 돌려주는 등의 일을 하도록 하면 됩니다.

 

6. sceneDidDisconnect(_ :)

scene이 background로 들어갔을 때 시스템이 자원을 확보하기 위해 disconnect하려고 할 수도 있습니다. (disconnect는 app을 종료시킨 것과는 다르다고 합니다! scene이 이 메소드로 전달되면 session에서 끊어진다는 것 뿐입니다.) 이 메소드 내에서 해야 할 가장 중요한 작업은 필요 없는 자원은 돌려주는 것입니다. 가령 디스크로나 네트워크를 통해 쉽게 불러올 수 있거나 생성이 쉬운 데이터들은 돌려주고, 사용자의 input과 같이 재생성이 어려운 데이터는 갖고 있게끔 하는 작업을 해주어야 합니다.

'iOS' 카테고리의 다른 글

[iOS] ViewController 안에 Static cell을 가진 TableView를 쓰고 싶을 때  (0) 2021.01.27
[iOS] AppDelegate & SceneDelegate  (2) 2021.01.17
[Swift] defer 구문  (0) 2021.01.16
[Swift] Optional  (0) 2021.01.12
[Swift] Optional  (0) 2021.01.12
댓글
댓글쓰기 폼