你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> [IOS 開發學習總結-OC-62]IOS 應用的生命周期

[IOS 開發學習總結-OC-62]IOS 應用的生命周期

編輯:IOS開發綜合

【IOS 開發學習總結-OC-62】IOS 應用的生命周期

IOS 應用的運行有前台運行和後台運行的差異。當應用在前台與後台之間切換的時候,系統會發出通知,回調應用程序委托類的特定方法,我們可以通過重寫這些方法來改變應用程序在前台和後台的運行行為。

IOS應用程序的狀態

IOS應用程序有如下幾種狀態;
1. not running:——程序未啟動或被系統禁止;
2. inactive(不活動):在前台運行,但不能接手事件處理。——當應用從一個狀態切換到另一個狀態時,中途過渡會短暫處於這種狀態;
3. active:在前台運行且能接收事件。——在前台時的正常狀態;
4. background:應用在後台運行,且在執行代碼。大多數將要進入掛起 suspended 狀態的應用,會短暫進入該狀態。若應用請求更多額外的執行時間,該應用會在此狀態保持更長一段時間。(如果一個應用要求啟動時直接進入後台運行,這樣的應用會直接從not running 進入background狀態,不經過inactive狀態)
5. suspended(掛起):應用處在後天,沒有執行任何代碼——系統會自動轉入該狀態,並且不會發出任何通知。(處在該狀態時,依然留駐內存,但不執行任何程序代碼。當系統發生低內存警告時,系統會將處於該掛起狀態的應用徹底移除內存,為前台釋放更多內存)

下圖為應用狀態切換示意圖:
這裡寫圖片描述

大部分時候,應用程序的狀態的改變都會激發應用程序委托類(app delegate)對應的方法。

協議中定義的這些方法的作用:

- (void)applicationWillResignActive:(UIApplication *)application
說明:當應用程序將要入非活動狀態執行,在此期間,應用程序不接收消息或事件,比如來電話了 - (void)applicationDidBecomeActive:(UIApplication *)application
說明:當應用程序入活動狀態執行,這個剛好跟上面那個方法相反 - (void)applicationDidEnterBackground:(UIApplication *)application
說明:當程序被推送到後台的時候調用。所以要設置後台繼續運行,則在這個函數裡面設置即可 - (void)applicationWillEnterForeground:(UIApplication *)application
說明:當程序從後台將要重新回到前台時候調用,這個剛好跟上面的那個方法相反。 - (void)applicationWillTerminate:(UIApplication *)application
說明:當程序將要退出是被調用,通常是用來保存數據和一些退出前的清理工作。這個需要要設置UIApplicationExitsOnSuspend的鍵值。 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
說明:iPhone設備只有有限的內存,如果為應用程序分配了太多內存操作系統會終止應用程序的運行,在終止前會執行這個方法,通常可以在這裡進行內存清理工作防止程序被終止 - (void)applicationSignificantTimeChange:(UIApplication*)application
說明:當系統時間發生改變時執行 - (void)applicationDidFinishLaunching:(UIApplication*)application
說明:當程序載入後執行 - (void)application:(UIApplication)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame
說明:當StatusBar框將要變化時執行 - (void)application:(UIApplication*)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration
說明:當StatusBar框方向將要變化時執行 - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url
說明:當通過url執行 - (void)application:(UIApplication*)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
說明:當StatusBar框方向變化完成後執行 - (void)application:(UIApplication*)application didChangeSetStatusBarFrame:(CGRect)oldStatusBarFrame
說明:當StatusBar框變化完成後執行

應用程序啟動過程

應用啟動時,從 no running——》inactive(短暫)——》active狀態。
或者:從 no running——》直接到後台運行狀態。

應用啟動時,系統會創建一個進程和一個主線程,並在主線程裡調用 main()函數——負責初始化 UIApplication 對象,並為UIApplication設置應用代理類等。

應用程序初始化並准備進到前台運行之前的大部分工作都在main()函數中完成。

應用啟動到 active 狀態的過程——加載應用程序進入前台

這裡寫圖片描述

加載應用程序進入後台

這裡寫圖片描述

如何確定應用是進入了前台還是進入了後台

可以在- (void)applicationDidFinishLaunching:(UIApplication*)application方法中判斷 UIApplication 對象的 applicationState 屬性——如果應用進入了前台,則該屬性值為 UIApplicationStateInactive;而如果進入了後台,屬性值為UIApplicationStateBackground. 示例代碼:UIApplicationState appState=[UIApplication sharedApplication].applicationState;該代碼可以用來檢測應用將要進入的狀態。

程序入口函數——main 函數

main函數是程序啟動的入口,在iOS app中,main函數的功能被最小化,它的主要工作都交給了UIKit framework

#import   

int main(int argc, char *argv[])  
{  
    @autoreleasepool {  
 return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));  
    }  
}  

UIApplicationMain函數會創建一個UIApplication對象,UIApplicationMain函數有四個參數,你不需要改變這些參數值,不過我們也需要理解這些參數和程序是如何開始的

argc——代表用戶傳入的參數個數 和argv——封裝了用戶傳入的多個參數。 第三個參數確定了主要應用程序類的名稱,這個參數指定為nil,這樣UIKit就會使用默認的程序類UIApplication。第四個參數是程序自定義的代理類名,這個類負責系統和代碼之間的交互,處理狀態切換中的產生的各種事件。它一般在Xcode新建項目時會自動生成。

另外 UIApplicationMain函數加載了程序主界面的xib設計文件。雖然這個函數加載了界面文件,但是沒有放到應用程序的windows上,你需要在Delegate的 application:willFinishLaunchingWithOptions方法中加載它。 但如果是storyboard界面是設計文件——該函數不僅會加載主界面設計文件,還會在用戶界面顯示在窗口中。

一個應用程序可以有一個主的storyboard文件或者有一個主的nib文件,但不能同時有兩個存在。

如果程序在啟動時沒有自動加載主要的故事版或nib文件,你可以在application:willFinishLaunchingWithOptions方法裡准備windows的展示。或者在項目設置界面或者 plist 文件中進行修改。

響應中斷的處理

當一個基於警告式的中斷發生時,比如有電話打進來了,這是程序會臨時進入inactive狀態,這用戶可以選擇如何處理這個中斷。
用戶決定如何處理該中斷之前,應用將一直處於 inactive 狀態,——用戶選擇後,當前應用可以返回 active 狀態繼續運行,也可以切到後台狀態,讓其他應用運行。

通知不會把程序變成為激活狀態,通知會顯示在banana狀態欄上,如果你拉下狀態欄,程序會變成inactive,把狀態欄放回去,程序變回active。

按鎖屏鍵也是另外一種程序的中斷,當你按下鎖屏鍵,系統屏蔽了所有觸摸事件,把app放到了後台,這時app狀態是 inactive,並進入後台。

流程如下圖:
這裡寫圖片描述

當有這些中斷時,我們的app該怎麼辦?

我們應該在applicationWillResignActive:方法中:

停止timer 和其他周期性的任務 停止任何正在運行的請求 停止正在運行的元數據查詢 暫停視頻的播放 如果是游戲那就暫停它 減少OpenGL ES的幀率

暫停所有執行非關鍵代碼的調度隊列和操作隊列(處於 inactive 狀態,但可以繼續處理網絡請求和其他耗時的後台任務)

掛起任何分發的隊列和不重要的操作隊列(你可以繼續處理網絡請求或其他時間敏感的後台任務)。

當程序回到active狀態 , applicationDidBecomeActive: 方法中恢復剛才applicationWillResignActive:方法中所有的工作。比如重新開始timer, 繼續分發隊列,提高OpenGL ES的幀率。不過游戲要回到暫停狀態,不能自動開始。

如果鎖屏時設置了密碼保護,設備內所有文件都處於保護狀態。——所以,如果應用持有這些被保護文件的引用,應該在applicationWillResignActive:方法中關閉這些引用,並在applicationDidBecomeActive: 方法中重新打開這些文件的引用。

通話過程中調整應用的 UI

我們使用 iPhone 的時候,都會發現當我們在接聽電話時(不掛斷),回到應用界面時,通知欄會高度變高。如下圖中上面的狀態欄:
這裡寫圖片描述
這個時候,如果我們應用的 UI 不變化的話,應用界面就會被狀態欄遮擋。處理這個問題的最好方法是——使用視圖控制器去管理應用程序界面。當狀態欄大小發生改變時,視圖控制器可自動調整它管理的所有內部視圖。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPsjnufvTptPD08nT2sSz0KnUrdLyw7vT0Mq508PK0828v9jWxsb3LNTy06a4w8rWtq/P7NOm17TMrMC4tcSx5LuvoaMmbWRhc2g7Jm1kYXNoO82ouf3XorLhVUlBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0JhckZyYW1lTm90aWZpY2F0aW9uzajWqsC0yrXP1qGjuMPNqNaqtcS0psDtuq/K/dOmu/HIode0zKzAuLXEuN+2yCyyosq508PV4rj2yv2+3crKtbG199X7tbHHsNPDu6e958PmtcS437bIoaM8L3A+DQo8YmxvY2txdW90ZT4NCgk8cD48c3Ryb25nPtaqyrbAqdW5o7o8L3N0cm9uZz5VSURldmljZU9yaWVudGF0aW9uRGlkQ2hhbmdlTm90aWZpY2F0aW9uus1VSUFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVOb3RpZmljYXRpb248L3A+DQo8L2Jsb2NrcXVvdGU+DQo8aDEgaWQ9"進入後台">進入後台

前台應用一般先切換到inactive 狀態,然後再切換到 background 狀態,系統自動調用應用委托的applicationWillResignActive:方法和- (void)applicationDidEnterBackground:(UIApplication *)application方法。

大部分應用在執行- (void)applicationDidEnterBackground:(UIApplication *)application方法執行完成後不久轉入 suspended 狀態。

對於請求特定後台任務的應用(如播放音樂)或請求需要額外執行時間的應用,可能會繼續執行更長時間。

這裡寫圖片描述

轉入後台要做的

應用可以在- (void)applicationDidEnterBackground:(UIApplication *)application方法中完成轉入後台前需要的准備工作,所有的應用要做的事情:
- 保存用戶數據或狀態信息。——所有沒有寫入磁盤的文件或信息在進入後台之前,都應該寫入磁盤。因為程序可能在後台被 killed。
- 釋放所有可以釋放的內存。

applicationDidEnterBackgound:方法有大概5秒的時間讓你完成這些任務。如果超過時間還有未完成的任務,你的程序就會被終止而且從內存中清除。如果還需要長時間的運行任務,可以調用 beginBackgroundTaskWithExpirationHandler 方法去請求後台運行時間和啟動線程來運行長時間運行的任務。
無論是否啟動執行後台任務的線程,applicationDidEnterBackgound:方法必須在5秒的時間內退出。

後台應用的內存使用

應用轉入後台,應該盡可能釋放它占用的內存。當系統內存緊張,系統會優先中中止那些占用大量內存且處於後台的應用。

在後台時,每個應用程序都應該釋放最大的內存。系統努力的保持更多的應用程序在後台同時 運行。不過當內存不足時,會終止一些掛起的程序來回收內存,那些內存最大的程序首先被終止。

事實上,應用程序應該的對象如果不再使用了,那就應該盡快的去掉強引用,這樣編譯器可以回收這些內存。如果你想緩存一些對象提升程序的性能,你可以在進入後台時,把這些對象去掉強引用。

下面這樣的對象應該盡快的去掉強引用:

緩存的圖片對象; 你可以重新加載的大的視頻或數據文件 任何當前沒用而且可以輕易創建的對象

在後台時,為了減少程序占用的內存,系統會自動執行如下操作釋放內存。

系統回收Core Animation的後備存儲; 去掉任何系統引用的緩存圖片; 去掉系統管理數據緩存中的強引用。

返回前台

流程如圖所示:
這裡寫圖片描述
- (void)applicationWillEnterForeground:(UIApplication *)application方法應該用來恢復所有在- (void)applicationDidEnterBackground:(UIApplication *)application方法中所做的 工作。
同時,在- (void)applicationDidBecomeActive:(UIApplication *)application方法中,應該執行那個在應用啟動時所做的操作。

當app處於掛起狀態時,它是不能執行任何代碼的。因此它不能處理在掛起期間發過來的通知,比如方向改變,時間改變,設置的改變還有其他影響程序展現的或狀態的通知。在程序返回後台或前台時,程序都要正確的處理這些通知。

應用程序終止

程序只要符合以下情況之一,只要離開前台進入後台或掛起狀態就會終止並移出內存:
1. iOS4.0以前的系統
2. app是基於iOS4.0之前系統開發的。
3. 設備不支持多任務
4. 在Info.plist文件中,程序包含了 UIApplicationExitsOnSuspend 鍵。

app如果被終止使處於前台或後台運行 ,系統會調用app的代理的方法 applicationWillTerminate: 這樣可以讓你可以做一些清理工作。

注意:如果應用當前處於 suspended 狀態,那麼該應用將要終止時不會調用applicationWillTerminate:方法。


通常來說,我們可以在該方法中保存用戶數據或應用狀態信息,保證應用重新啟動可以恢復之前的運動狀態。
你可以保存一些數據或app的狀態。這個方法也有5秒鐘的限制。超時後方法會返回程序從內存中清除。

注意:用戶可以手工關閉應用程序。

The Main Run Loop ——主運行循環

Main Run Loop負責處理用戶相關的事件。UIApplication對象在程序啟動時啟動main run Loop,它處理事件和更新視圖的界面。看Main Run Loop就知道,它是運行在程序的主線程上的。這樣保證了接收到用戶相關操作的事件是按順序處理的。

Main Run Loop 處理事件的架構圖:
這裡寫圖片描述

用戶操作設備,相關的操作事件被系統生成並通過UIKit的指定端口分發。事件在內部排成隊列,一個個的分發到Main run loop 去做處理。UIApplication對象是第一個接收到事件的對象,它決定事件如何被處理。觸摸事件分發到主窗口,窗口再分發到對應出發觸摸事件的View。其他的事件通過其他途徑分發給其他對象變量做處理。

大部分的事件可以在你的應用裡分發,類似於觸摸事件,遠程操控事件(線控耳機等)都是由app的 responder objects 對象處理的。

iOS 應用中,絕大部分對象都可以作為UIResponder對象。
Responder objects 在你的app裡到處都是,比如:UIApplication 對象。view對象,view controller 對象,都是resopnder objects。大部分事件的目標都指定了resopnder object,不過事件也可以傳遞給其他對象。比如,某個 UIResponder對象 不處理事件,可以傳給它對應的 UIviewcontroller(如果有),如果UIviewcontroller也不處理該事件,事件將會被傳給它所在的 UIView

補充學習資料:
1. 該參考文檔中有些內容不是很全面,也不是很准確,對比學習啦。 iOS應用程序生命周期(前後台切換,應用的各種狀態)詳解
2. iOS系統消息
3. iOS開發系列–通知與消息機制

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved