iOS 應(yīng)用的生命周期

背景

隨著App幾年以來不斷的迭代開發(fā),各種sdk集成,日志監(jiān)控,bugly接入等等,啟動(dòng)時(shí)間越來越長(zhǎng),深入了解下ios程序啟動(dòng)運(yùn)行狀態(tài),為后續(xù)的啟動(dòng)優(yōu)化做準(zhǔn)備。

了解應(yīng)用生命周期有什么意義?

iOS系統(tǒng)的資源是有限的,如何能利用有限的資源,發(fā)揮出最大的作用,這就是一個(gè)優(yōu)秀的程序猿應(yīng)該思考的問題。

應(yīng)用程序不同狀態(tài)切換時(shí),需要處理的工作也不相同。不同的狀態(tài),處理不同的代碼,
這樣可以優(yōu)化用戶的體驗(yàn)和電池性能,而且冷啟動(dòng)時(shí)長(zhǎng)是App性能的重要指標(biāo)

了解應(yīng)用程序的狀態(tài)

狀態(tài) 說明
Not running 未運(yùn)行 程序沒啟動(dòng)
Inactive 未激活 程序在前臺(tái)運(yùn)行,不過沒有接收到事件。
Active 激活 程序在前臺(tái)運(yùn)行而且接收到了事件。
Backgroud 后臺(tái) 程序在后臺(tái)而且能執(zhí)行代碼,大多數(shù)程序進(jìn)入這個(gè)狀態(tài)后會(huì)在在這個(gè)狀態(tài)上停留一會(huì)。時(shí)間到之后會(huì)進(jìn)入掛起狀態(tài)(Suspended)。有的程序經(jīng)過特殊的請(qǐng)求后可以長(zhǎng)期處于Backgroud狀態(tài)
Suspended 掛起 程序在后臺(tái)不能執(zhí)行代碼。系統(tǒng)會(huì)自動(dòng)把程序變成這個(gè)狀態(tài)而且不會(huì)發(fā)出通知。當(dāng)掛起時(shí),程序還是停留在內(nèi)存中的,當(dāng)系統(tǒng)內(nèi)存低時(shí),系統(tǒng)就把掛起的程序清除掉,為前臺(tái)程序提供更多的內(nèi)存。


狀態(tài)圖:


狀態(tài)圖.png

ios程序入口main函數(shù)

一般所有基于C編寫的app的入口都是main函數(shù),但iOS應(yīng)用程序有點(diǎn)不同。你無需自己創(chuàng)建main函數(shù),在使用Xcode創(chuàng)建工程的時(shí)候就已經(jīng)幫你提供了。除非一些特殊情況,否則你不應(yīng)該修改Xcode提供的main函數(shù)實(shí)現(xiàn)。
在ios的App中,大大弱化了main函數(shù),它的主要工作都交給了UIKit framework
示例代碼如下:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

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

UIApplicationMain:一個(gè)很重要的函數(shù),它主要是創(chuàng)建app的幾個(gè)核心對(duì)象來處理以下過程:

  1. 從可用Storyboard文件加載用戶界面
  2. 調(diào)用AppDelegate自定義代碼來做一些初始化設(shè)置
  3. 將app放入Main Run Loop環(huán)境中來響應(yīng)和處理與用戶交互產(chǎn)生的事件

注:一個(gè)應(yīng)用程序可以有一個(gè)主的storyboard文件或者有一個(gè)主的nib文件,但不能同時(shí)有兩個(gè)存在。

每個(gè)iPhone應(yīng)用程序都有一個(gè)UIApplication,它主要有2個(gè)任務(wù)。
1、負(fù)責(zé)初始化并顯示UIWindow,負(fù)責(zé)加載應(yīng)用程序的第一個(gè)UIView到UIWindow窗體中。
2、幫助管理應(yīng)用程序的生命周期,UIApplicationDelegate的代理類來履行這個(gè)任務(wù)。
雖然UIApplication 會(huì)負(fù)責(zé)接收事件,但是UIApplicationDelegate則決定應(yīng)用程序如何去響應(yīng)這些事 件,包括應(yīng)用程序的生命周期事件(比如程序啟動(dòng)和關(guān)閉)、系統(tǒng)事件(比如來電、記事項(xiàng)警 告)

此處只闡述代理方法:

應(yīng)用程序完成啟動(dòng)以后調(diào)用的方法didFinishLaunchingWithOptions:
didFinishLaunchingWithOptions的幾種啟動(dòng)類型介紹

/// 這個(gè)方法是你在啟動(dòng)時(shí)的第一次機(jī)會(huì)來執(zhí)行代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return YES;
}

應(yīng)用程序即將從活躍狀態(tài)切換到不活躍狀態(tài)時(shí)調(diào)用applicationWillResignActive:

/**
 這種情況會(huì)在某些臨時(shí)中斷的事情下發(fā)生(比如來電話,來短信等)或者用戶退出應(yīng)用程序時(shí)發(fā)生。
 并且應(yīng)用程序開始轉(zhuǎn)換到后臺(tái)狀態(tài)。
 后臺(tái)切換到前臺(tái):   后臺(tái) ---> 不活躍狀態(tài) --> 前臺(tái)(活躍狀態(tài))
 前臺(tái)切換到后臺(tái):   前臺(tái)(活躍狀態(tài)) --> 不活躍狀態(tài) --> 后臺(tái)
 */
- (void)applicationWillResignActive:(UIApplication *)application{
    NSLog(@"%@", NSStringFromSelector(_cmd));
    //使用這個(gè)方法,我們可以暫停正在執(zhí)行的任務(wù),停用定時(shí)器,降低OpenGL ES的描繪幀率,游戲應(yīng)該在這個(gè)方法中暫停。
}

應(yīng)用程序進(jìn)入到后臺(tái)后調(diào)用的方法applicationDidEnterBackground:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // 在這個(gè)方法中,我們可以釋放共享的資源,保存用戶數(shù)據(jù),使定時(shí)器無效,并且保存足夠多的應(yīng)用程序狀態(tài)信息用來恢復(fù)應(yīng)用程序當(dāng)前的狀態(tài)。
    // 配置應(yīng)用程序是否能夠在后臺(tái): 在Info.plist添加一項(xiàng):Application does not run in background YES 不支持后臺(tái)運(yùn)行 NO  支持后臺(tái)運(yùn)行
    // 當(dāng)用戶退出應(yīng)用程序時(shí),如果你的應(yīng)用程序支持后臺(tái)運(yùn)行,這個(gè)方法會(huì)被調(diào)用.如果你的應(yīng)用程序不支持后臺(tái)運(yùn)行,applicationWillTerminate:這個(gè)方法會(huì)被調(diào)用。
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

應(yīng)用程序即將進(jìn)入到前臺(tái)時(shí)調(diào)用的方法applicationWillEnterForeground:

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // 這個(gè)方法作為從后臺(tái)進(jìn)入不活躍狀態(tài)的時(shí)候調(diào)用的方法。在這兒,你可以撤銷在進(jìn)入后臺(tái)后做的許多改變。(恢復(fù)用戶數(shù)據(jù))
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

應(yīng)用程序已經(jīng)成為活躍狀態(tài)后調(diào)用的方法applicationDidBecomeActive:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // 在這個(gè)方法中,重啟之前被暫停的任務(wù)(或者還沒有啟動(dòng)的任務(wù)),如果應(yīng)用程序之前在后臺(tái)運(yùn)行,我們可以選擇刷新用戶界面。
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

應(yīng)用程序即將終止時(shí)調(diào)用applicationWillTerminate:

- (void)applicationWillTerminate:(UIApplication *)application {
   // 在這個(gè)方法中保存合適的數(shù)據(jù)。    
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

應(yīng)用程序收到內(nèi)存警告時(shí)調(diào)用的方法applicationDidReceiveMemoryWarning:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    // 釋放暫時(shí)無用的資源
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

示例:

1、運(yùn)行程序會(huì)調(diào)用如下代理方法:


image.png

2、按Home


image.png

3、再次點(diǎn)擊程序


image.png

4、只有當(dāng)應(yīng)用被系統(tǒng)殺死的時(shí)候才會(huì)調(diào)用這個(gè)方法:applicationWillTerminate
什么時(shí)候會(huì)調(diào)用applicationWillTerminate

5、當(dāng)收到推送通知的時(shí)候會(huì)調(diào)用這個(gè)方法:applicationWillResignActive

6、在彈出的通知橫幅處向上滑動(dòng),讓橫幅消失:applicationDidBecomeActive

參考文章:
App Programming Guide for iOS
https://www.cnblogs.com/jukaiit/p/5615492.html
http://ios.dovov.com/applicationwillterminate-3.html
https://blog.csdn.net/totogo2010/article/details/8048652
http://m.itdecent.cn/p/fc675b077756
https://blog.csdn.net/totogo2010/article/details/8048652
http://m.itdecent.cn/p/aa50e5350852

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 0. 引子 iOS應(yīng)用程序一般都是由自己編寫的代碼和系統(tǒng)框架(system frameworks)組成,系統(tǒng)框架提...
    i愛吃土豆的貓閱讀 617評(píng)論 0 0
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,685評(píng)論 1 32
  • 國(guó)慶成都四天三晚旅游攻略 1號(hào)中午到成都后在車站坐地鐵到錦江賓館站,下車后掃小黃車導(dǎo)航到民民宿放行李。下午的行程從...
    Hha_0f53閱讀 321評(píng)論 0 1
  • 池莉女兒 李袡 我把女兒教進(jìn)世界名校
    drunkfufu閱讀 155評(píng)論 0 1
  • 苦度春秋天涯客 露珠岌岌溢清澈 心懷日月抱乾坤 阿爾卑斯一孤鶴
    拾殤F_H閱讀 94評(píng)論 0 0

友情鏈接更多精彩內(nèi)容