iOS Lifecycle - toant-dev/toandev.github.io GitHub Wiki

App Lifecycle

https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle

  • Not Running: the app is considered to be in a Not Running state when it is not yet launched or terminated by the system or user.
  • Inactive: the app is in an inactive state when it is in the foreground but receiving events. In other words, we can say that it acts like a bridge state in which the app remains briefly when it transitions to a different state.
  • Active: it is a normal mode for the app when it is in the foreground state and receiving all the user events.
  • Background: the app transitions into the background state when the user taps on the home screen while using the application, or it requires some extra execution time. When the app is about to be suspended, then also transitions into this state for a small amount of time. In this state, the app remains in the background and executes the code.
  • Suspended: in this state, the app remains in the background and doesn't execute the code. The app is automatically moved to this state. In this state, the app remains in memory. However, the foreground apps are always given priority over suspended apps and can be purged any time without notice.
  • Not running: thì sẽ là trạng thái lúc app không được bật, hoặc là bị terminated (có thể do user force hoặc do system).

  • Active: là app đang chạy, có nghĩa là đang trên foreground, thì app vẫn nhận và xử lý events bình thường.

  • Inactive: app vẫn ở trên foreground, nhưng lúc này app không thể xử lý events (có thể là bị chen ngang bởi một tác vào khác). Hoặc đây cũng là một trạng thái khi app transit từ foreground xuống background.

  • Background: là lúc này app đã xuống background, nhưng vẫn có thể thực thi được một số tasks nếu có đăng ký background task với OS.

  • Suspended: app ở background nhưng không thể thực thi được các tasks. Thường thì do chính system sẽ tự động đưa app về trạng thái này. Lúc này thì app vẫn còn trong memory.

User launch app lên, app sẽ được chạy trên foreground, ngay sau đó app sẽ được nhảy vào trạng thái active. Trong lúc đang sử dụng app, thì có một số tác vụ khác chen ngang, ví dụ như có cuộc gọi đến, hoặc đơn giản hơn là khi user vuốt xuống notification center, hoặc vuốt lên control center, thì lúc này app sẽ rơi vào trạng thái inactive. Inactive cũng là trạng thái để transit từ active qua các trạng thái khác (xuống background hoặc là user quit app). Khi user bấm nút home để về màn hình chính, app sẽ xuống trạng thái background, vào sau một khoản thời gian ngắn, nếu app không xử lý bất cứ tác vụ gì thì sẽ được system tự động chuyển về trạng thái suspended (có thể hiểu là trạng thái đóng băng, vì app lúc này sẽ không nhận được bất cứ thông báo gì) mà không cần báo trước. Cơ chế này có thể hiểu là system làm vậy để nhường tài nguyên hệ thống cho các app đang tương tác với user ở foreground (ví dụ CPUs,..), cũng một phần để tiết kiệm pin vì lúc này user không cần làm việc với app. Xử lý tác vụ trong background ở đây có thể hiểu là app đăng ký background task với system để có thể chạy được dưới background, system sẽ cấp một khoản thời gian để task thực thi tác vụ đó

Cuối cùng là trạng thái terminated, để app rơi vào trạng thái terminated thì sẽ có 2 tình huống:

  • Một là user force quit bằng cách kill app trong multitasking.

  • Hai là lúc app đang trong trạng thái suspended (vẫn còn được lưu trong memory), system có thể terminated app của chúng ta để nhường bộ nhớ cho các app khác ở foreground.

Một lưu ý đó là, khi app đã ở trong trạng suspended thì khi system terminate app thì app sẽ không nhận được bất cứ thông báo gì về việc này.

Trong thực tế, với một số app đơn giản thì sẽ cũng chẳng cần app phải được giữ trong memory (về suspended) khi cho app xuống background, mà khi app vừa xuống background sẽ terminate app ngay lập tức để trả lại memory cho system. Đối với trường hợp như vậy thì ta cần đăng ký một key UIApplicationExitsOnSuspend và set bằng YES trong file info.plist của app.

UIApplicationDelegate

  • application: didFinishLaunchingWithOptions:-> Bool: when the application is launched initially, this method is called. We can do any initial setup for the application in this method like firebase configuration, user navigation, etc. The storyboard is loaded at this point, but we can maintain the state restoration.
  • applicationWillEnterForeground: this method is called after didFinishLaunchingWithOptions. It is also called when the application comes from background to foreground.
  • applicationDidBecomeActive: this method is called after applicationWillEnterForeground. If we need to perform any particular task when the app comes into the foreground, like font update, etc., then we can place the code in this method.
  • applicationWillResignActive: this method is notified when the application is about to become inactive. For example, the user receives a phone call; the user presses the home button, etc.).
  • applicationDidEnterBackground: this method is notified when the application goes into a background state after become inactive.
  • applicationWillTerminate: this method is called when the application is about to be finally terminated from memory. If we need to perform any final cleanups, then we can place the code in this method.

New iOS 13

UIApplicationDelegate

  1. func application(_:didFinishLaunchingWithOptions:) -> Bool
  2. func application(_:configurationForConnecting:options:) -> UISceneConfiguration
  3. func application(_:didDiscardSceneSessions:)

Some notification handler + deeplink

UISceneDelegate

  1. scene(_:willConnectTo:options:)
  2. sceneDidDisconnect(_:)
  3. sceneDidBecomeActive(_:)
  4. sceneWillResignActive(_:)
  5. sceneWillEnterForeground(_:)
  6. sceneDidEnterBackground(_:)

View Controller lifecycle

  • loadView This method use when view Controller create from code .Its good not to do anything on this method .If view Controller made from .xib or storyboard. What Do in View Load : loadView( ) is a method managed by the viewController. The viewController calls it when its current view is nil. loadView( ) basically takes a view (that you create) and sets it to the viewController’s view (superview).
  • viewDidLoad: This Method is loaded once in view controller life cycle .Its Called When all the view are loaded .You Can do Some common task in this method : 1.Network call which need Once. 2.User Interface 3.Others Task Those are Need to do Once Note: This Method Call before the bound are defined and rotation happen.So its Risky to work view size in this method.
  • viewWillAppear: This Method is called every time before the view are visible to and before any animation are configured .In this method view has bound but orientation not set yet.You can override this method to perform custom tasks associated with displaying the view such as to hide fields or disable actions before the view becomes visible.
  • viewWillLayoutSubviews: It don’t do Nothing by default. When a view’€™s bounds change, the view adjusts the position of its subviews. View controller can override this method to make changes before the view lays out its subviews.
  • viewDidLayoutSubviews: This method is called after the viewController has been adjust to its subview following a change on its bound.Add code here if you want to make change to subviews after they have been set.
  • viewDidAppear: This Method is called after the view present on the screen. Usually save data to core data or start animation or start playing a video or a sound, or to start collecting data from the network This type of task good for this method.
  • viewWillDisappear: This method called before the view are remove from the view hierarchy.The View are Still on view hierarchy but not removed yet . any unload animations haven’t been configured yet. Add code here to handle timers, hide the keyboard, cancel network requests, revert any changes to the parent UI. Also, this is an ideal place to save state.
  • viewDidDisappear: This method is called after the VC’s view has been removed from the view hierarchy. Use this method to stop listening for notifications or device sensors.
  • deinit: Before a view controller is removed from memory, it gets deinitialized. You usually override deinit() to clean resources that the view controller has allocated that are not freed by ARC. Keep in mind that just because a VC is no longer visible, doesn’t mean that it has been deallocated. Container view controllers such as NavigationController can keep their VCs available in memory. Keep in mind that even though a VC is off screen, if it is still in memory, it still works normally and can receive notifications.
  • didReceiveMemoryWarning() When memory starts to fill up, iOS does not automatically move data from memory to its limited hard disk space. It does, however, issue this warning and YOU (I mean YOU) are responsible for clearing some objects out of memory. Be aware that if the memory of your app goes over a certain threshold, iOS will shutdown your app. Unfortunately, this will look like a crash to the end user.
  • viewWillTransition(to:with:) When the interface orientation changes, UIKit calls this method on the window’s root view controller before the size changes are about to be made. The root view controller then notifies its child view controllers, propagating the message throughout the view controller hierarchy. The parameter to contains the new CGSize size of the container’s view and the parameter with contains a UIViewControllerTransitionCoordinator coordinator, an enum that describes the new orientation.

Flow Screen 1 > Screen 2 > Screen 1

  • Screen 1: ViewDidLoad

  • Screen 1: ViewWillAppear

  • Screen 1: ViewDidAppear

  • Screen 2: ViewDidLoad

  • Screen 1: ViewWillDisappear

  • Screen 2: ViewWillAppear

  • Screen 1: ViewDidDisappear

  • Screen 2: ViewDidAppear

  • Screen 2: ViewWillDisappear

  • Screen 1: ViewWillAppear

  • Screen 2: ViewDidDisappear

  • Screen 1: ViewDidAppear