应用程序的生命周期

之前对于应用程序的生命周期,和Appdelegate类在应用程序的不同阶段回调的不同方法一直存在这很大疑问,今天下午特意查阅相关资料对此了解。

先从一个程序的启动说起吧

 

1.Not running(非运行状态) -----》2.inactive(前台非活跃状态)----------》3.Active(前台活跃状态)-------》Background (后台状态) --------》suspended(挂起状态)

 

       当然这些箭头并不是单向的,不同的场景会有不同的方式

比如说可能从Background (后台状态) ----》inactive(前台非活跃状态);

再比如说从suspended(挂起状态)------》Background (后台状态) ;

当然在发出内存警告,或者用户主动关闭后台程序时会从suspended(挂起状态)---》Not running(非运行状态)。

 

1.Not running (非运行状态):我们的应用没有运行。

2.Inactive(前台非活跃状态):应用程序正在进入前台,但还不能接受事件的处理。

3.Active(前台活跃状态):应用程序进入前台状态,而且能接受事件的处理

4.Background(后台状态):应用进入后台,依然能够执行代码,但是一旦执行玩可执行的代码,应用马上就会进入我们常说的挂起状态。

5.Suspended(挂起状态):处于该状态的程序,仿佛进入了一种冰冻状态,不能执行代码。且如果系统的内存不够,应用程序会被终止。

 

    下面我们也说说AppDelegate中那些代理方法,我把项目中的注释在网上翻译了一下,感觉并不怎么好,于是有查阅了我最近买的一本书。感觉还勉强能把那些方法说明白点吧。

//  Copyright (c) 2015年 王志豪imac. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

//app加载完毕的时候调用(一般只调用一次)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //翻译: 应用程序启动后覆盖点定制
    // Override point for customization after application launch.
    
    //说明: 应用程序启动并进行初始化时调用的方法,这个阶段会实例化根视图控制器
    NSLog(@"程序加载完毕");
    
    
    
    return YES;
}
//程序失去焦点的时候调用(控件不能接受事件)
- (void)applicationWillResignActive:(UIApplication *)application {
    
    
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    //翻译:发送时,应用程序是从活动到非活动状态。这可能会出现某些类型的临时中断(如来电或短信)或当用户退出应用程序,它开始过渡到背景状态(后台)
    
    
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    //翻译:用这种方法来暂停正在进行的任务,禁用定时器,和油门下的OpenGL ES的帧速率。游戏应该用这种方法来暂停游戏
    
    NSLog(@"程序失去焦点");
    
    //说明 : 应用程序从活跃状态到非活跃状态时调用,这个阶段可以保存UI状态(例如游戏状态)
}


//app进入后台的时候调用(app消失不见)
- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    //翻译:用这种方法释放共享资源,保存用户数据,无效计时器,并储存足够的应用程序状态信息来恢复您的应用程序的当前状态的情况下,终止后。
    
    
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    //翻译:如果您的应用程序支持后台执行,这种方法被称为替代applicationWillTerminate:当用户退出。  (注:applicationWillTerminate 是当程序结束时调用的方法,一般情况下不会调用)
    
    NSLog(@"程序进入后台");
    
    //说明: 应用程序进入后台时调用,该方法。这个阶段可以保存用户数据,释放一些资源(例如释放数据资源库)
}

//当app进入前台的时候调用的方法(app显示出来)
- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    
    //翻译:称为从背景(后台)到非活动状态的过渡的一部分;在这里,您可以撤消进入背景(后台)的许多更改。
    
    //说明: 应用程序进入前台,但是还没有处于活动状态,这个阶段可以恢复用户数据
    NSLog(@"程序进入前台");
}

//当程序获得焦点的时候调用(只有程序获得焦点  所有的控件才能接受事件)
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    //翻译:重新启动任何已暂停的任务(或尚未开始),而应用程序处于非活动状态。如果应用程序在后台,可以随意刷新用户界面。
    //说明: 应用程序进入前台,并处于活动状态时调用的方法,这个阶段可以恢复UI的状态。(例如游戏的状态)。
    NSLog(@"程序获得焦点");
}


//当程序结束的时候调用(一般不会调用,)当程序进入后台,时会进入休眠状态,要想调用这个方法,必须把休眠状态关掉。(把Info.plist中的Application does not run in background改为YES就行默认为NO)
- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    //翻译:当应用程序即将终止时调用。如果适当的话,保存数据。又见applicationDidEnterBackground有
    
    NSLog(@"程序结束");
    
    //说明: 应用程序被终止,时调用,但内存清除时除外,这个阶段可以释放一些资源,也可保存用户数据。
}

@end

其实这看代码并不能清楚他们之间到底什么时候调用。

下面我也学学那些大神们模拟几个场景,可能不是太准确,但至少也算能够说明情况。

  1》非运行状态-----》到应用启动

     当你点击APP图标,或者说,你运行程序吧。当然也可能是从后台到前台。

在这个过程中:主要有下面三个状态

Not running(非运行状态)-------->Inactive(前台非活跃状态)------------->Active(前台活跃状态)

 

在Not running(非运行状态)-------->Inactive(前台非活跃状态)时:

//app加载完毕的时候调用(一般只调用一次)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //翻译: 应用程序启动后覆盖点定制
    // Override point for customization after application launch.
    
    //说明: 应用程序启动并进行初始化时调用的方法,这个阶段会实例化根视图控制器
    NSLog(@"程序加载完毕");
    
    
    
    return YES;
}

Inactive(前台非活跃状态)------------->Active(前台活跃状态)时调用:

 

//当程序获得焦点的时候调用(只有程序获得焦点  所有的控件才能接受事件)
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    //翻译:重新启动任何已暂停的任务(或尚未开始),而应用程序处于非活动状态。如果应用程序在后台,可以随意刷新用户界面。
    //说明: 应用程序进入前台,并处于活动状态时调用的方法,这个阶段可以恢复UI的状态。(例如游戏的状态)。
    NSLog(@"程序获得焦点");
}
2》点击Home建 ---------应用消失不见(后台)
     当然这里的场景是在应用处于(前台活跃状态)时点击Home键。又或者说其他应用导致当前正在运行的程序中断。
其实这个情况还是有点复杂的。首先程序进入后台后 有俩种情况,之前我也是迷惑了一段,感觉有必要把他的来龙去脉摸清楚了。在属性文件(Info.plist)中有一个叫做 Application does not run in background的属性(默认是NO)也就是应用程序可以在后台运行或者挂起。同样如果设置成YES应用程序不可以在后台运行或者挂起。
你可以参照下图去设置一下,试试效果如何。

 

说完上面的一些大致场景,那么让我先从第一种情况:应用程序可以在后台运行或者挂起说起吧。
这个阶段主要有四个状态:
从Active(前台活跃状态)---->Inactive(前台非活跃状态)---------->Background(后台状态)----->Suspended(挂起状态);
第一阶段:从Active(前台活跃状态)---->Inactive(前台非活跃状态)调用:
//程序失去焦点的时候调用(控件不能接受事件)
- (void)applicationWillResignActive:(UIApplication *)application {
    
    
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    //翻译:发送时,应用程序是从活动到非活动状态。这可能会出现某些类型的临时中断(如来电或短信)或当用户退出应用程序,它开始过渡到背景状态(后台)
    
    
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    //翻译:用这种方法来暂停正在进行的任务,禁用定时器,和油门下的OpenGL ES的帧速率。游戏应该用这种方法来暂停游戏
    
    NSLog(@"程序失去焦点");
    
    //说明 : 应用程序从活跃状态到非活跃状态时调用,这个阶段可以保存UI状态(例如游戏状态)
}
第二阶段:Inactive(前台非活跃状态)---------->Background(后台状态)
这个阶段我也不清楚调用什么方法。
 
第三阶段:Background(后台状态)----->Suspended(挂起状态)调用
//app进入后台的时候调用(app消失不见)
- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    //翻译:用这种方法释放共享资源,保存用户数据,无效计时器,并储存足够的应用程序状态信息来恢复您的应用程序的当前状态的情况下,终止后。
    
    
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    //翻译:如果您的应用程序支持后台执行,这种方法被称为替代applicationWillTerminate:当用户退出。  (注:applicationWillTerminate 是当程序结束时调用的方法,一般情况下不会调用)
    
    NSLog(@"程序进入后台");
    
    //说明: 应用程序进入后台时调用,该方法。这个阶段可以保存用户数据,释放一些资源(例如释放数据资源库)
}
那么让我们接着说第二种情况吧
应用程序不可以在后台运行或者挂起。
Active(前台活跃状态)------>Inactive(前台非活跃状态)--------->Background(后台状态)----->Suspended(挂起状态)-------->Not running (非运行状态);
这种情况,一共五个状态四个阶段。
 
第一阶段:Active(前台活跃状态)------>Inactive(前台非活跃状态):

 

 
//程序失去焦点的时候调用(控件不能接受事件)
- (void)applicationWillResignActive:(UIApplication *)application {
    
    
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    //翻译:发送时,应用程序是从活动到非活动状态。这可能会出现某些类型的临时中断(如来电或短信)或当用户退出应用程序,它开始过渡到背景状态(后台)
    
    
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    //翻译:用这种方法来暂停正在进行的任务,禁用定时器,和油门下的OpenGL ES的帧速率。游戏应该用这种方法来暂停游戏
    
    NSLog(@"程序失去焦点");
    
    //说明 : 应用程序从活跃状态到非活跃状态时调用,这个阶段可以保存UI状态(例如游戏状态)
第二阶段:Inactive(前台非活跃状态)--------->Background(后台状态)调用
还不清楚,调用什么方法。
 
第三阶段Background(后台状态)----->Suspended(挂起状态)
//app进入后台的时候调用(app消失不见)
- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    //翻译:用这种方法释放共享资源,保存用户数据,无效计时器,并储存足够的应用程序状态信息来恢复您的应用程序的当前状态的情况下,终止后。
    
    
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    //翻译:如果您的应用程序支持后台执行,这种方法被称为替代applicationWillTerminate:当用户退出。  (注:applicationWillTerminate 是当程序结束时调用的方法,一般情况下不会调用)
    
    NSLog(@"程序进入后台");
    
    //说明: 应用程序进入后台时调用,该方法。这个阶段可以保存用户数据,释放一些资源(例如释放数据资源库)
}
第四阶段:Suspended(挂起状态)-------->Not running (非运行状态)调用

 

//当程序结束的时候调用(一般不会调用,)当程序进入后台,时会进入休眠状态,要想调用这个方法,必须把休眠状态关掉。(把Info.plist中的Application does not run in background改为YES就行默认为NO)
- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    //翻译:当应用程序即将终止时调用。如果适当的话,保存数据。又见applicationDidEnterBackground有
    
    NSLog(@"程序结束");
    
    //说明: 应用程序被终止,时调用,但内存清除时除外,这个阶段可以释放一些资源,也可保存用户数据。
}
上面那个场景不知道描述的够不够准确,可能有好多不足之处。
当从 后台(挂起)到应用重新运行起来。也会调用一些方法
uspended(挂起状态)-----》Background(后台状态)————》Inactive(前台非活跃状态)————》Active(前台活跃状态)
第一阶段我不是太清楚调用了什么方法。
 
第二阶段,Background(后台状态)————》Inactive(前台非活跃状态)
调用了

 

 
//当app进入前台的时候调用的方法(app显示出来)
- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    
    //翻译:称为从背景(后台)到非活动状态的过渡的一部分;在这里,您可以撤消进入背景(后台)的许多更改。
    
    //说明: 应用程序进入前台,但是还没有处于活动状态,这个阶段可以恢复用户数据
    NSLog(@"程序进入前台");
}

 

第三阶段:Inactive(前台非活跃状态)————》Active(前台活跃状态)
//当程序获得焦点的时候调用(只有程序获得焦点  所有的控件才能接受事件)
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    //翻译:重新启动任何已暂停的任务(或尚未开始),而应用程序处于非活动状态。如果应用程序在后台,可以随意刷新用户界面。
    //说明: 应用程序进入前台,并处于活动状态时调用的方法,这个阶段可以恢复UI的状态。(例如游戏的状态)。
    NSLog(@"程序获得焦点");
}
基本上以上场景都能说明问题了。
 
不过还有一种情况,这种情况很少发生,就是当你在玩手机时,发出内存警告,为了解决内存问题,会把你在后台挂起的程序终止。在这里我也就不模拟场景了。
 
    其实我想说的是另外一种情况就是程序加载完成时调用的方法。实在是不想打字了,复制我以前做的笔记了,也可以说明一些情况。
 

程序启动的完整过程

1.main函数

 

2.UIApplicationMain

*创建UIApplication对象

*创建UIApplication的delegate对象

 

3.delegate对象开始处理(监听)系统事件(没有storyboard的情况)

*程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法

*在application:didFinishLaunchingWithOptions:中创建UIWindow

*创建和设置UIWindow的rootViewController

* 显示窗口

 

3.根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)

*创建UIWindow

*创建和设置UIWindow的rootViewController

* 显示窗口

这样我们的程序就能显示在手机屏幕上了。
 

 

-------------------代码永无止境。

 

posted @ 2015-09-17 17:31  悲了伤的老王  阅读(210)  评论(0编辑  收藏  举报