剛開始接觸 iOS 開發的時候,就對新專案一開始就給定的 viewDidLoad()
方法有一些疑問,經過詢問才知道要查關鍵字「生命週期」(life cycle),大部分文章都是談論 View Controller 的生命週期,其實 App 本身也是有生命週期,就把這兩種生命週期分開來談,今天主題是介紹 App 的生命週期,但因為 iOS 13 之後,蘋果改成 swiftUI 來開發,此篇文章是在更改前就已經完成的,所以只適用於 iOS 12 以下以及 Xcode 10 開新專案時看到的方法,詳細差異可參考官網。
每個 iOS 的 app 在它的生命週期皆有五種狀態。
Not running: 未運行狀態,app 還沒有被啟動過,或者已經被系統從暫停狀態清理掉了,此時 app 不會存在記憶體中。
Inactive: 未活躍狀態,app 正在運行並處於前台,但是無法接收任何事件,通常發生在狀態轉換的時期,而在這個狀態停留的時間一般都非常短暫,許多 app 都會使用一些畫面來渡過此階段。
Active: 活躍狀態,正在運行並處於前台,app 可以開始接收與回傳事件,UI 也可以開始運作,即是我們平常在用的 app。
Background: 後台運行狀態,程序處於後台並可以執行代碼(用戶切換到別的程序),當 app 進入後台後,iOS 只會留給程序很短暫的一點時間進行數據清理或保存工作,之後就會將程序進入暫停狀態。
Suspended: 暫停狀態,app 還活著,在後台且繼續佔有內存,但不會執行任何代碼,iOS 會保持這個狀態一段時間,以便快速響應用戶重新回到 app,但如果系統內存吃緊,就會優先殺掉這個狀態的進程。當下一次我們重新打開 app 時,app 就會重新回到後台運行狀態,再回到非啟動狀態,最後達到啟動狀態,進入可以使用的狀態。注意:系統從後台運行狀態轉到暫停狀態不會有任何通知。
下圖顯示與 app delegate object 有關的狀態切換,app 開啟後,系統會將 app 放在待用或背景的狀態中,取決於 UI (User Interface) 是否出現在螢幕上。當 app 啟動到前台時,系統會將 app 自動轉為活躍的狀態。至此之後,狀態在活躍與背景之間波動,直到 app 終止(適用 iOS 12 及以下版本)。
使用 app transitions 執行以下任務:
App delegate 是 app 的核心,它負責處理 app 的初始化、狀態的轉換和許多高階 app 的事件。此物件也是保證會出現在每一個 app,所以它通常用來設定 app 初始的資料結構。 App delegate 運用在整個 app 中,可以利用它來管理 app的生命週期,而 ViewController 則是用在單一的視圖。一個 app 可以有許多的視圖,但只會有一個 App delegate。
application: willFinishLaunchingWithOptions
程序正在被啟動,但還沒有到前台,可以在這裡做第一次的初始化動作,如檢查 options 等。
application:didFinishLaunchingWithOptions
程序已經完成系統初始化工作,但依然還沒有到前台,可以在這裡做最終的初始化動作;這兩個回調都是 app 被第一次觸發時才會回調的,其他從後台暫停到前台是不會觸發這兩個的。
applicationDidBecomeActive
已經處於活躍狀態,這裡就可以開始做事。
applicationWillResignActive
程序馬上就要進入後台。
applicationDidEnterBackground
app 已經進入後台,並可能隨時會被暫停,做狀態保存吧;當然也可以在這裡請求延長後台任務的執行。
applicationWillEnterForeground
通知你程序馬上就要進入前台啦,但此時還不能響應事件,還不是活躍狀態,正在活躍狀態後會回調 applicationDidBecomeActive
方法,所以先在這裡恢復狀態吧。
applicationWillTerminate
程序將被殺掉(該回調只會在程序處於後台且非掛起的狀態下被殺掉),系統內存不足時,系統會殺掉後台的程序,在這裡做善後工作吧;而如果系統是殺掉的掛起的程序,則不會有任何通知;用戶主動殺掉進程的機制跟此類似。