1. 应用程序的生命周期
1.1 应用程序的状态
应用程序在整个生命周期中会在五种状态之间不断转换。
- Not running:未运行,程序没有启动。
- Inactive:未激活,程序在前台运行,但没有接收到任何事件,或被其他任务强制占用了,例如突然来了电话、程序在前台时手机自动锁屏等。在没有事件处理情况下程序通常停留在这个状态。
- Active:激活,程序在前台运行而且接收到事件。这也是前台的一个正常的模式。
- Backgroud:后台,程序在后台但能执行代码,大多数程序进入后台状态后,只会在后台状态上停留一段时间,当时间到了之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态而不进入挂起状态(Suspended)。
- Suspended:挂起,程序在后台不能执行代码。系统会自动把后台程序变成这个状态而且不会发出通知。当挂起时,程序仍驻留在内存中。当系统内存不足时,系统就会把挂起的程序清除掉,为前台的程序提供更多的内存。
2. AppDelegate
APP启动时基本上每一次的状态改变都会调用一些delegate中的方法来响应当前的状态,让我们可以对程序进行特定操作。
2.1 willFinishLaunching
willFinishLaunching:程序将要完成启动。只在程序启动时执行一次。launchOptions:存存储程序启动的原因。
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
2.2 didFinishLaunching
didFinishLaunching:程序已经完成启动,将要显示界面了。只在程序启动时执行一次。launchOptions:存存储程序启动的原因。
didFinishLaunching是在app显示界面给用户之前最后执行的状态,理所当然我们可以在这个方法内完成一些基本的初始化,但是应该是轻量级的初始化操作,不然会导致程序启动时间长,影响用户体验。
举一些栗子:
- 不使用StoryBoard,需要配置window
- 第三方登录sdk注册,以及很多第三方sdk的初始化配置
- 判断程序接下来的业务逻辑,播不播放引导图片?播不播放开屏广告?有没有登录?
但项目复杂了之后,需要配置的东西越来越多,所以didFinishLaunching非常容易耦合,这是我们应该要注意的。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//若用户直接启动,launchOptions内无数据。
//若由其他程序通过openURL:启动。
//launchOptions中UIApplicationLaunchOptionsURLKey的数据为openURL:的参数url。
//launchOptions中UIApplicationLaunchOptionsSourceApplicationKey的数据为启动本程序的源程序的bundle ID(NSString)。
NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
if (url) {
[self launchOptionsWithURL:url];
}
NSString *bundleId = [launchOptions objectForKey:UIApplicationLaunchOptionsSourceApplicationKey];
if (bundleId) {
[self launchOptionsWithBundleId:bundleId];
}
//若由远程通知启动。
//launchOptions中UIApplicationLaunchOptionsRemoteNotificationKey对应数据为启动本程序的远程通知信息useinfo(NSDictionary)。
NSDictionary *useinfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (useinfo) {
[self launchOptionsWithUseinfo:useinfo];
}
return YES;
}
2.3 DidBecomeActive
DidBecomeActive:程序已激活。程序在处于前台时调用:程序第一次启动时、从后台返回前台时。
若程序之前在后台,可以在这方法内重新拉取数据,刷新用户界面。
- (void)applicationDidBecomeActive:(UIApplication *)application;
2.4 WillResignActive
WillResignActive:程序将要进入未激活。程序在处于前台时调用:有电话打进来、手机锁屏等。程序被其他任务强制占用了,就会调用这个方法,所以这个方法也称为程序中断调用方法。
实际运用场景为:
- 对音频、视频、游戏的暂停操作
- 暂停定时器
- 减少OpenGL ES帧率
- 暂停正在执行的任务,若有下载任务可以取消或暂停。
- (void)applicationWillResignActive:(UIApplication *)application {
}
2.5 DidEnterBackground
DidEnterBackground:程序已经进入后台。程序从前台进入后台时调用。
作用是:
- 释放共享资源
- 保存用户数据(写到硬盘)
- 作废计时器
- 保存足够的程序状态以便下次恢复
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
2.6 WillEnterForeground
WillEnterForeground:程序将要进入前台。程序从后台进入前台时调用。
WillEnterForeground主要用于撤销WillResignActive中做的操作。
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
2.7 WillTerminate
WillTerminate:程序将要终止。程序终止之前调用。
目的就是为了保留一些重要的数据,方便下次启动后的恢复,达到一种让用户感觉该程序永远运行在后台从来没被终止过的感觉。
- (void)applicationWillTerminate:(UIApplication *)application {
[self saveContext];
}
下面给出这些方法的交互先后顺序:
1、启动程序:
--willFinishLaunchingWithOptions
--didFinishLaunchingWithOptions
--DidBecomeActive
2、按下Home键:
--WillResignActive
--DidEnterBackground
3、重新点击程序:
--WillEnterForeground
--DidBecomeActive