Weekoding

[Swift] 생명주기 정리( App / ViewController ) 본문

공부 노트(Swift)

[Swift] 생명주기 정리( App / ViewController )

Weekoding 2022. 5. 22. 22:58

기기에 맞추어 constraint를 변경한다거나, 

데이터를 불러와서 setting할 때,

화면 혹은 앱이 끝나서 데이터를 처리하거나

background에서 처리할 것이 있을 때(금융 앱들은 정보보호 차원으로 화면이 가려지는 등)

 

생명주기를 잘 알고 대응해야 적절한 타이밍에 작업을 할 수 있다.

App과 ViewController의 LifeCycle에 대해 정리해 보자.

 

 

🔄 App LifeCycle

우선, App LifeCycle과 관련된 동작들은 SceneDelegateAppDelegate에서 이루어진다.

Xcode Project를 생성하면 기본적으로 생성이 되어있는 파일들이다.

 

Before start :

iOS 12 이하 - AppDelegate가 모든 역할을 담당했다.

iOS 13 이상 - Scene이라는 개념이 도입되어 SceneDelegate가 등장하게 되었다.

 

12 이하일 때는 하나의 앱이 하나의 Window를 가진다는 개념이었다.

그러나 13부터 Window의 개념이 Scene으로 대체되고, 하나의 앱은 여러 Scene을 가질 수 있게 되었다.

두 개의 UI를 가진 앱의 등장

포스팅 시점은 iOS 15 까지 등장한 상태이지만,

Legacy 코드를 접할 수 있으므로 해당 변경사항을 숙지하고 각 파일들의 역할과 메소드를 짧게 알아보자.

 

AppDelegate: 

  • App의 데이터 구조 초기화
  • App의 Scene에 대한 Configuration( 환경설정 )
  • App 밖에서 오는 알림에 대응( ex: 배터리 부족, 다운로드 완료 )
  • App 자체를 targeting하는 이벤트에 대응( 특정 View, ViewController, Scene ❌ )
  • 실행시 요구되는 Service 등록( ex: Apple Push Notification Center )
  • SceneSession을 통해 Scene에 대한 정보를 업데이트 받는다.

SceneSession: Scene 고유의 런타임 인스턴스를 관리. 고유 식별자와 Scene의 세부 구성사항이 들어있다.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
   // Override point for customization after application launch.
      = 이 곳에서 App 자체에 대한 각종 setup을 진행. launch시 호출 

   return true
}

// 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.
      = App launch가 아닌, 새로운 scene/window를 제공할 때 불리는 메소드.

   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.       
      = 사용자가 scene을 폐기할 때 호출되는 메소드.
}

위 세가지 메소드는 프로젝트 생성 시 AppDelegate에 기본적으로 구현되어 있는 메소드들이다.

다음 메소드들은 사용자가 필요에 따라 작업을 구현할 수 있는 메소드들이며, App LifeCycle과 관련이 있다.

func applicationWillEnterForeground(_ application: UIApplication) {
   //Application이 Foreground로 진입하는 상태    
}
    
func applicationWillResignActive(_ application: UIApplication) {
   //Application이 Background로 진입하는 과정 중 일부로,
   //Active상태를 벗어날 때를 의미한다. 이때, inActive상태를 거쳐간다.
}
    
func applicationDidEnterBackground(_ application: UIApplication) {
   //Application이 Background로 진입하는 상태.
   //앱이 종료된 것은 아니며, 메모리를 차지하고 있다. 마무리 작업을 한다.
   //전화가 올 때처럼 interrupt에 의해 Background로 진입할 수 있다.
}
    
func applicationDidBecomeActive(_ application: UIApplication) {
   //Background상태에서 다시 Active상태가 될 때를 의미한다.
   //이때, inActive상태를 거쳐간다.
}
    
func applicationWillTerminate(_ application: UIApplication) {
   //Background상태에서 메모리를 반납하고 종료된다.
   //너무 오래 Background상태에서만 머물고 있으면 OS에 의해 Terminate 된다.
}

 

 

SceneDelegate: 

iOS13 이후의 개념으로, UI의 상태를 알 수 있는 UILifeCycle을 관리하는 역할(AppDelegate로부터 넘겨받은 셈)

scene의 LifeCycle 순서에 맞추어 정리하였다.

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 } 
        
   = 새로운 UIWindow를 생성하여 scene에 연결하고, rootViewController를 설정.
     Storyboard를 사용하면 자동으로 초기화 되며, 그렇지 않을 때는 이곳에서 추가 설정이 필요.
     보통 code로 UI를 짤 때, 첫 view를 만들 때 쓰임.
}

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.
      = scene이 background → foreground(혹은 처음 active)로 전환될 때 호출되는 메소드.
        background상태로 돌입할 때의 변화들을 다시 원상복귀 시키는 작업을 한다.
}

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.
      = inactive → active상태로 scene이 돌입할 때 호출되는 메소드
        scene이 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).
      = scene이 active → inactive 상태로 빠질 때 호출된다
        추가로, 이러한 전환은 interrupt에 의해 일어날 수 있다(ex) 전화가 왔을 때)
}

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.
      = scene이 foreground → background 상태로 돌입할 때 호출된다.
        data를 저장하고, 공유 중이던 자원을 돌려주거나 
        다시 scene이 foreground로 돌입할 때 필요한 data들을 처리하는 작업을 한다.
}

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).
      = scene이 폐기되거나 background상태에 들어갈 때 호출되는 메소드.
        scene이 사용하던 자원을 돌려주는 작업을 한다.
        scene은 폐기될 필요가 없다면 다시 연결될 수 있다.(disconnect는 app 종료와는 다른 개념임.)
}

Life Cycle(Scene-Based)

  • Unattached :  scene이 연결되지 않은(unattached) 상태
  • Active           :  App이 실행중이며 이벤트를 받은 상태
  • Inactivive     :  App이 실행중이며 이벤트를 받지 않은 상태
  • Suspended  :  Background에 있고, 실행되는 code가 없는 상태

 

 

 

 

🔄 ViewController / View LifeCycle

출처:&nbsp;https://velog.io/@delmasong/Understand-the-View-Controller-LifeCycle

한눈에 LifeCycle을 파악할 수 있는 사진을 발견했다.

보는 바와 같이 View자체의 상태는 4가지로 나눌 수 있고, 관련된 메소드는 총 6가지이다.

 

 

View의 상태(4가지)

  • Appearing
  • Appeared
  • Disappearing
  • Disappeared

영단어 의미 각각 그대로 보여지는 상태 • 보여진(완료된) 상태 • 사라지는 상태사라진(완료된) 상태이다.

 

 

 

View의 상태에 관한 메소드(6가지)

View 상태에 따라 ViewController에서 호출되는 메소드가 다르다.

 

viewDidLoad()

  -  View가 메모리에 로드될 때 호출되는 메소드. 따라서 처음 생성될 때만 한번 호출된다.

  -  이 곳에서 ViewController의 setup을 구현한다.

 

viewWillAppear()

  -  View가 화면에 보여지기 시작할 때(View 계층에 추가되기 전에) 호출되는 메소드. 따라서 여러번 호출될 수 있다.

  -  이 곳에서 보여지지 않다가 보여질 때, Update가 필요한 부분들을 구현한다.

 

viewDidAppear()

  -  View가 화면에 보여진 후(View 계층에 추가된 후) 호출되는 메소드.

  -  이 곳에서 View가 화면에 보여지자 마자(사용자가 화면을 마주한 직후) 처리할 부분들을 구현한다.

 

viewWillDisappear()

  -  View가 화면에서 사라지기 시작할 때(View 계층에 제거되기 전) 호출되는 메소드.

  -  이 곳에서 View가 사라지기 전 작업내용을 Rollback하거나, data를 저장하는 부분을 구현한다.

 

viewDidDisappear()

  -  View가 화면에서 사라진 뒤(View 계층에서 제거된 후) 호출되는 메소드.

  -  이 곳에서 View가 사라지는 것과 관련된 작업들을 구현한다.

  -  View는 사라졌지만 메모리에서 삭제된 것은 아니다.

 

 

 

정리  📌

App LifeCycle:

Scene LifeCycle을 관리하는 SceneDelegate

App 단위의 설정을 관리하거나 Event에 대응하는 AppDelegate로 관리가 된다.

 

ViewController / View LifeCycle:

View의 상태를 appearing, appeared, disappearing, disappeared의 4가지로 정의하고,

이에 따라 ViewController가 6가지의 메소드를 호출하여 LifeCycle 관리가 이루어진다.

 

 

 

 

 

오류 및 지적사항은 댓글로 남겨주시면 감사하겠습니다!

참고 : 

https://sueaty.tistory.com/134

https://velog.io/@dev-lena/iOS-AppDelegate%EC%99%80-SceneDelegate

https://velog.io/@delmasong/Understand-the-View-Controller-LifeCycle

Comments