iOS 应用的生命周期

背景

随着App几年以来不断的迭代开发,各种sdk集成,日志监控,bugly接入等等,启动时间越来越长,深入了解下ios程序启动运行状态,为后续的启动优化做准备。

了解应用生命周期有什么意义?

iOS系统的资源是有限的,如何能利用有限的资源,发挥出最大的作用,这就是一个优秀的程序猿应该思考的问题。

应用程序不同状态切换时,需要处理的工作也不相同。不同的状态,处理不同的代码,
这样可以优化用户的体验和电池性能,而且冷启动时长是App性能的重要指标

了解应用程序的状态

状态 说明
Not running 未运行 程序没启动
Inactive 未激活 程序在前台运行,不过没有接收到事件。
Active 激活 程序在前台运行而且接收到了事件。
Backgroud 后台 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态
Suspended 挂起 程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。


状态图:


状态图.png

ios程序入口main函数

一般所有基于C编写的app的入口都是main函数,但iOS应用程序有点不同。你无需自己创建main函数,在使用Xcode创建工程的时候就已经帮你提供了。除非一些特殊情况,否则你不应该修改Xcode提供的main函数实现。
在ios的App中,大大弱化了main函数,它的主要工作都交给了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:一个很重要的函数,它主要是创建app的几个核心对象来处理以下过程:

  1. 从可用Storyboard文件加载用户界面
  2. 调用AppDelegate自定义代码来做一些初始化设置
  3. 将app放入Main Run Loop环境中来响应和处理与用户交互产生的事件

注:一个应用程序可以有一个主的storyboard文件或者有一个主的nib文件,但不能同时有两个存在。

每个iPhone应用程序都有一个UIApplication,它主要有2个任务。
1、负责初始化并显示UIWindow,负责加载应用程序的第一个UIView到UIWindow窗体中。
2、帮助管理应用程序的生命周期,UIApplicationDelegate的代理类来履行这个任务。
虽然UIApplication 会负责接收事件,但是UIApplicationDelegate则决定应用程序如何去响应这些事 件,包括应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警 告)

此处只阐述代理方法:

应用程序完成启动以后调用的方法didFinishLaunchingWithOptions:
didFinishLaunchingWithOptions的几种启动类型介绍

/// 这个方法是你在启动时的第一次机会来执行代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return YES;
}

应用程序即将从活跃状态切换到不活跃状态时调用applicationWillResignActive:

/**
 这种情况会在某些临时中断的事情下发生(比如来电话,来短信等)或者用户退出应用程序时发生。
 并且应用程序开始转换到后台状态。
 后台切换到前台:   后台 ---> 不活跃状态 --> 前台(活跃状态)
 前台切换到后台:   前台(活跃状态) --> 不活跃状态 --> 后台
 */
- (void)applicationWillResignActive:(UIApplication *)application{
    NSLog(@"%@", NSStringFromSelector(_cmd));
    //使用这个方法,我们可以暂停正在执行的任务,停用定时器,降低OpenGL ES的描绘帧率,游戏应该在这个方法中暂停。
}

应用程序进入到后台后调用的方法applicationDidEnterBackground:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // 在这个方法中,我们可以释放共享的资源,保存用户数据,使定时器无效,并且保存足够多的应用程序状态信息用来恢复应用程序当前的状态。
    // 配置应用程序是否能够在后台: 在Info.plist添加一项:Application does not run in background YES 不支持后台运行 NO  支持后台运行
    // 当用户退出应用程序时,如果你的应用程序支持后台运行,这个方法会被调用.如果你的应用程序不支持后台运行,applicationWillTerminate:这个方法会被调用。
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

应用程序即将进入到前台时调用的方法applicationWillEnterForeground:

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // 这个方法作为从后台进入不活跃状态的时候调用的方法。在这儿,你可以撤销在进入后台后做的许多改变。(恢复用户数据)
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

应用程序已经成为活跃状态后调用的方法applicationDidBecomeActive:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // 在这个方法中,重启之前被暂停的任务(或者还没有启动的任务),如果应用程序之前在后台运行,我们可以选择刷新用户界面。
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

应用程序即将终止时调用applicationWillTerminate:

- (void)applicationWillTerminate:(UIApplication *)application {
   // 在这个方法中保存合适的数据。    
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

应用程序收到内存警告时调用的方法applicationDidReceiveMemoryWarning:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    // 释放暂时无用的资源
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

示例:

1、运行程序会调用如下代理方法:


image.png

2、按Home


image.png

3、再次点击程序


image.png

4、只有当应用被系统杀死的时候才会调用这个方法:applicationWillTerminate
什么时候会调用applicationWillTerminate

5、当收到推送通知的时候会调用这个方法:applicationWillResignActive

6、在弹出的通知横幅处向上滑动,让横幅消失: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
https://www.jianshu.com/p/fc675b077756
https://blog.csdn.net/totogo2010/article/details/8048652
https://www.jianshu.com/p/aa50e5350852

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容

  • 0. 引子 iOS应用程序一般都是由自己编写的代码和系统框架(system frameworks)组成,系统框架提...
    i爱吃土豆的猫阅读 500评论 0 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,034评论 1 32
  • 国庆成都四天三晚旅游攻略 1号中午到成都后在车站坐地铁到锦江宾馆站,下车后扫小黄车导航到民民宿放行李。下午的行程从...
    Hha_0f53阅读 263评论 0 1
  • 池莉女儿 李袡 我把女儿教进世界名校
    drunkfufu阅读 94评论 0 1
  • 苦度春秋天涯客 露珠岌岌溢清澈 心怀日月抱乾坤 阿尔卑斯一孤鹤
    拾殇F_H阅读 68评论 0 0