iOS-App生命周期
官方文档:
基本要点:
一 入口函数为main函数,一般不需要更改;
发散点:看main函数,可以注意到加上了@autoreleasepool. 实际上如果在启动子线程的时候,也需要作类似处理,以保证放入auto release pool的对象能被及时释放.
二 The Main Run Loop 主运行循环
Main Run Loop负责处理用户相关的事件。UIApplication对象在程序启动时启动main run Loop,它处理事件和更新视图的界面, 是运行在程序的主线程上的。
发散点:NSRunLoop的学习与使用.
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:5]];
三 App States (应用程序状态)
1 Not running 未运行:程序没启动或者被系统终止;
2 Inactive 未激活:程序在前台运行,不过没有接收到事件。应用处于这个状态时,很多时候仅仅是当时正要转向另一个状态;
3 Active 激活:程序在前台运行而且接收到了事件。这也是前台的一个正常的模式。
4 Background 后台:程序在后台而且能执行代码。应用程序进入这个状态多半是因为要进入Suspended状态;应用程序在从Background转向Suspended状态之前可以请求额外的时间来完成一些后台的处理。In addition, an app being launched directly into the background enters this state instead of the inactive state.
5 Suspended 挂起:程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。
四 程序切换时AppDelegate收到的回调
-
application:willFinishLaunchingWithOptions: 应用程序启动时调用.一般不需要做特殊处理.
-
application:didFinishLaunchingWithOptions: 应用启动时调用,此时应用还没有展示给用户,停留在所谓的开机画面页,在这个方法中做一些必要的初始化操作,以前没有设置main story board进入的时候,是需要通过代码来alloc window并设置root view controller的. 注意在该方法中不要执行耗时操作,比如大量的IO操作等等,因为如果较长时间这个方法还没有执行完毕(测试的时候大概是30s左右),iOS会杀掉进程的.
-
applicationDidBecomeActive:应用程序进入到Active状态,意味着应用将要切换到前台.
-
applicationWillResignActive:
当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话 -
applicationDidEnterBackground:应用程序已经进入后台状态.
-
applicationWillEnterForeground: 应用程序将要进入前台的时候调用,在这个时候还没有变成Active状态.
-
applicationWillTerminate:
应用程序将要被系统终止,注意,如果应用已经是Suspended状态下这个方法不会被调用,所以如果想在程序被杀掉之前保存一些数据的话,需要注意尽量避免在这个方法中去做数据保存的事情
此外,还有方法
- (void)applicationDidFinishLaunching:(UIApplication *)application;
但是SDK文档明确说明,应该用- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions替代.
五 在实际开发过程中,我们发现,在iOS 7和iOS 8 上,root view controller的viewDidLoad和
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions中的方法执行的先后顺序是不同的,也没有看到明确的文档说明,可能也和设定root view controller的方式有关。
当时遇到的问题是,在root view controller的viewDidload方法中通过addObserver来观察一个后台任务是否执行完成;而这个后台任务在didFinishLaunchingWithOptions中启动。在iOS 7 上, viewDidload会在构造root view controller之后被先执行,这样addObserver会在后台任务发送消息之前先执行,整个流程没问题;但是iOS 8上,后台任务可能都已经执行完了,postNotification已经调用过了,root view controller的viewDidLoad还没有开始调用,导致addObserver没被调用而导致bug。
所以,建议两者之间不要有强关联,不要互相依赖对方的执行。
六 在applicationDidEnterBackground时,如果还希望长时间的运行任务,可以调用下面的方法:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"startBackgroundTask time out");
// do something .....
}];
除此以外,在执行这些回调函数的时候,应该尽快的执行完毕并返回。