iOS App生命周期及AppDelegate、SceneDelegate


iOS 12 及之前

一、APP的生命狀態:

  • Not running(未運行):程序未運行
  • Inactive(未激活):程序在前台運行,但沒有接收到事件。在沒有事件處理情況下程序通常停留在這個狀態。
  • Active ( 激活 ): 程序在前台運行而且接收到了事件。這也是前台的一個正常的模式。
  • Backgroud ( 后台 ): 程序在后台而且能執行代碼,大多數程序進入這個狀態后會在在這個狀態上停留一會。時間到之后會進入掛起狀態(Suspended)。有的程序經過特殊的請求后可以長期處於Backgroud狀態。
  • Suspended ( 掛起 ): 程序在后台但是卻不能執行代碼。系統會自動把程序變成這個狀態而且不會發出通知。當掛起時,程序還是停留在 內存中的,當系統內存低時,系統就把掛起的程序清除掉,為前台程序提供更多的內存。

二、 關於app生命周期中的各方法

func application(_:willFinishLaunchingWithOptions:)
func application(_:didFinishLaunchingWithOptions:)
// app初始化

func applicationDidBecomeActive(UIApplication)
// app已經被激活

func applicationWillResignActive(UIApplication)
// app即將被掛起

func applicationDidEnterBackground(UIApplication)
// app已經進入后台

func applicationWillEnterForeground(UIApplication)
// app即將回到前台

func applicationWillTerminate(UIApplication)
// app即將被殺死

三、App運行過程中根據狀態變化代理方法的調用順序

  • 啟動app:
application(_:willFinishLaunchingWithOptions:)
application(_:didFinishLaunchingWithOptions:)
applicationDidBecomeActive(UIApplication)
application:didReceiveRemoteNotification//接受處理消息通知
  • 雙擊home鍵使app上移掛起
applicationWillResignActive(UIApplication)
  • 再次雙擊home鍵使app下移歸位
applicationDidBecomeActive(UIApplication)
  • 單擊home鍵使app進入后台
applicationWillResignActive(UIApplication)
applicationDidEnterBackground(UIApplication)
  • 打開正運行在后台的app
applicationWillEnterForeground(UIApplication)
applicationDidBecomeActive(UIApplication)
  • 再次切到后台
applicationWillResignActive(UIApplication)
applicationDidEnterBackground(UIApplication)
  • 點擊通知中心里面的遠程推送,使App從后台 進入前台
applicationWillEnterForeground(UIApplication)
application:didReceiveRemoteNotification // 接收、處理消息通知
applicationDidBecomeActive(UIApplication)
  • 殺死App進程(終止程序)
applicationWillTerminate(UIApplication)
  • 從APP切換到微信之類的其他應用之后,再切換回來時
applicationWillEnterForeground(UIApplication)
application:openURL:sourceApplication // 應用間傳值
applicationDidBecomeActive(UIApplication)

iOS 13 之后

一、查看一下新的Xcode項目模板

在新的Xcode11當中創建新的項目,會看到自動生成AppDelegate.swiftSceneDelegate.swift文件。
除了這兩個委托文件之外,Xcode還做了其他一些事情。打開Info.plist,會看到一個叫做Application Scene Manifest的新key。

Enable Multiple Windows默認鍵值為NO,如果設置為YES則允許你的app在ipadOS中多開。
Application Session Role數組中:

  • Configuration的名稱,必須是唯一的
  • scene的代理類名,通常為SceneDelegate。
  • scene用於創建初始UI的storyboard名稱。(該設置可以在Xcode 12項目的Project Properties配置中找到。)

AppDelegate中的SceneDelegate、UISceneSession和Application Scene Manifest是如何一起創建多窗口應用的呢?

  • 首先,我們看SceneDelegate類。 它管理scene的生命周期,處理各種響應,諸如 sceneDidBecomeActive(😃 and sceneDidEnterBackground(:)之類的事件。
  • 然后,我們再看看AppDelegate類中的新函數。 它管理場景會話(scene sessions),提供scene的配置數據,並響應用戶丟棄scene的事件。
  • 最后,我們看了一下Application Scene Manifest。 它列出了應用程序支持的scene,並將它們連接到delegate類並初始化storyboard。

二、AppDelegate的新職責

AppDelegate仍然是iOS 13中應用程序的主要入口點。Apple為幾個應用程序級生命周期事件調用AppDelegate方法。在Apple的默認模板中,你會發現三個Apple認為對你來說很重要的方法:

func application(_:didFinishLaunchingWithOptions:) -> Bool
func application(_:configurationForConnecting:options:) -> UISceneConfiguration
func application(_:didDiscardSceneSessions:)

當你的應用程序剛剛啟動,func application(_ :didFinishLaunchingWithOptions:) -> Bool 被調用。此方法用於執行應用程序設置。在ios12或更早的版本中,你可能已經使用這個方法來創建和配置一個UIWindow對象,並將一個UIViewController實例分配給window以使它出現。

如果你的應用程序正在使用scene,你的AppDelegate將不再負責這一操作。由於應用程序現在可以有多個窗口,或者uiscenes處於active狀態,因此在AppDelegate中管理單個window對象沒有多大意義。

當你的app被期望提供一個新的scene或window供iOS顯示時,就會調用func application(_ :configurationForConnecting:options:) -> UISceneConfiguration。注意,當你的應用程序啟動時,這個方法不會被調用,它只會被調用來獲取和創建新的場景。 目前還沒有進行過多窗口的開發,后續再深入研究...

AppDelegate模板中的最后一個方法是func application(_ :didDiscardSceneSessions:)。每當用戶丟棄一個scene時,就會調用此方法,例如在多任務窗口中將該場景滑走。

除了這些默認方法之外,您的AppDelegate還可以用於打開url、捕獲內存警告、檢測應用程序何時終止、設備的時鍾是否發生了顯著變化、檢測用戶何時注冊了遠程通知等等。

Tip:
需要注意的是,如果你目前使用AppDelegate來管理應用的狀態欄外觀,你可能需要在ios13中做一些改變。在ios13中,一些狀態欄相關的方法已經被棄用。

三、SceneDelegate的職責

當AppDelegate是負責應用程序生命周期的對象時,SceneDelegate負責屏幕上顯示的內容(scenes or windows)。

當你處理scene時,對你的用戶來說看起來像window的東西實際上被稱為UIScene,它是由UISceneSession管理的。當我們提到windows時,我們實際上指的是UISceneSession對象。

code在創建項目時創建的SceneDelegate.swift文件中有幾個默認的方法:

scene(_:willConnectTo:options:)
sceneDidDisconnect(_:)
sceneDidBecomeActive(_:)
sceneWillResignActive(_:)
sceneWillEnterForeground(_:)
sceneDidEnterBackground(_:)

如果你熟悉iOS 13之前的AppDelegate,這些方法看起來應該很熟悉。
scene(:willConnectTo:options:),它是UISceneSession生命周期中調用的第一個方法。
scene(
:willConnectTo:options:)的默認實現會創建你的初始內容視圖(content view) (如果你使用的是SwiftUI,就會創建ContentView),並創建一個新的UIWindow,然后設置window的rootViewController,並讓這個window成為關鍵窗口。您可以將此窗口視為用戶看到的窗口。不幸的是,事實並非如此。Windows在ios13之前就已經出現了,它們代表應用程序運行的視口(viewport)。UISceneSession控制用戶看到的可見窗口,你創建的UIWindow是你的應用的容器視圖(container view)。

除了設置初始視圖外,還可以使用scene(_:willConnectTo:options:)來恢復場景UI,以防scene在過去斷開連接。例如,因為它被發送到后台。你也可以讀取connectionOptions對象來查看你的scene是由於一個切換請求或者打開一個URL而創建的。

一旦你的scene連接好了,scene生命周期中的下一個方法就是 sceneWillEnterForeground(😃 。此方法在你的scene將要走上舞台時調用。這可能是當你的應用從后台過渡到前台,或者它只是第一次被激活。接下來,調用sceneDidBecomeActive(😃。這是你的scene設置,可視化,並准備被使用的地方。

一個更有趣的方法是sceneDidDisconnect(_😃。當你的場景被發送到后台時,iOS可能會決定斷開並清除你的場景以釋放資源。這並不意味着你的應用程序被殺死或不再運行,它只是意味着傳遞給這個方法的場景不再活躍,並將從其會話斷開。

Tip:
會話本身並不一定要丟棄,iOS可能會決定在任何時候將場景重新連接到場景會話,例如當用戶再次將特定場景帶到前台時。

sceneDidDisconnect(_:)中要做的最重要的事情是放棄你不需要保留的任何資源。這些數據可以很容易地從磁盤或網絡加載,也可以很容易地重新創建。但是要確保你保留了那些無法輕松重新創建的數據,比如用戶在場景中提供的任何輸入,這些輸入在他們返回場景時仍然存在,具體的實現方法后續再深入研究。

Apple 建議我們把視圖層級相關的方法從 didFinishLanchingWithOptions 遷移到 SceneDelegate 中的 willConnectTo 方法中。這樣做有兩個好處:

  • 首先可以提高預覽結果呈現的速度
  • 其次在應用進入后台時,不會做一些額外的操作,只會做一些必要的操作,使應用快速進入睡眠狀態,以節省耗電.

總之

iOS13之前,appDelegate的職責全權處理App生命周期和UI生命周期;

iOS13之后,appDelegate的職責是:
  • 處理 App 生命周期
  • 新的 Scene Session 生命周期
  • 所有UI生命周期交給SceneDelegate處理,appDelegate不在負責UI生命周期

參考博客:
Understanding the iOS 13 Scene Delegate
iOS13 Scene Delegate詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM