从实践谈iOS生命周期
个人感觉生命周期无论在Android,还是iOS都是很重要的概念,因为在每个声明周期的状态下我们可以做很多预加载或者处理的操作。因此在这里主要总结下ViewController和AppDelegate中的一些状态。
应用程序的状态
看下这个图:
- Foreground :前台
- Background :后台
- Not running:应用程序并没有启动
- Inactive :应用程序运行在前台但是没有接收到事件响应
- Active :应用程序运行在前台接受到事件响应
- Background :运行在后台并且执行代码
- Suspended :运行在后台但是没有运行代码
APP启动
基本上每一次的状态改变都会调用一些delegate对象来响应当前的状态。就来介绍下这些delegate对象并且说明一些实际当中的使用
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSLog(@"willFinishLaunchingWithOptions");
return YES;
}
willFinishLaunchingWithOptions就是应用程序在启动的时候的一个状态,就是页面将要显示的时候的一个状态。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(@"didFinishLaunchingWithOptions");
return YES;
}
didFinishLaunchingWithOptions就是在应用程序在显示前最后一次的操作机会
可以看下验证:
既然是在app在显示app给用户之前执行的操作,理所当然我们可以在这里做一些基本的初始化的操作,但是应该是一些轻量级的初始话操作,否则会影响用户体验。举一些例子:
- 我用代码写UI,没有使用StoryBoard,就会在这里配置下window
- 还有就是例如你有一些Fabric之类的插件做数据分析的,AdMob广告之类的初始化其实都可以放在这里的。
- 甚至是AFNetworking的startMonitor这些初始化操作都能放在这里
但是分析下,willFinishLaunchingWithOptions和didFinishLaunchingWithOptions描述上差不多,但是又有什么本质的区别呢?
个人感觉在使用上其实并没有太大的区别,但是本质的区别我觉得跟Android的onStart和onResume有一些类似,在Android中他们的区别是根据Activity是否可见这个角度说明的,其实就是一个准备前跟准备完成后的区别,willFinishLaunchingWithOptions是声明当前的进程已经启动但是还没有进入状态保存,那么didFinishLaunchingWithOptions就是声明所有基本的准备工作已经完成,可以开始启动了,因此刚才谈到的一些实际场景的应用基本上都是在didFinishLaunchingWithOptions做的。
再启动这里还有另一个状态,看下代码:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(@"applicationDidBecomeActive");
}
整个的启动过程其实是这样的,app启动之后,状态由not running变换为inactive,接着调用上面提到的两个方法,接着就是由inactive切换到active状态,这个时候会调用applicationDidBecomeActive,这里就不演示了,感兴趣可以自己看看,因此,在锁屏,来回切换App都会调用applicationDidBecomeActive方法。
App发生中断
中断情况典型的可能就是有人打电话进来,这个时候就会进入inactive状态,准备进入后台,这里会调用
- (void)applicationWillResignActive:(UIApplication *)application {
NSLog(@"applicationWillResignActive");
}
实际应用中就是一些暂停操作:
- 例如对视频的暂停操作
- 对音乐的暂停操作
- 游戏的话可能有的也需要暂停
- 将一些不重要的任务都挂起,你要是还有下载任务的话,可以考虑结束它或者是暂停它,当然要是NSURLSession的话,如果我们下载的东西不大的话,可以考虑不管它
App从后台切回
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"applicationWillEnterForeground");
}
App将要从后台切回来,此时调用这个方法,在这里我们需要做的就是考虑你的应用需不需要更新啊,是否需要从server去拉数据呀。
基本上就可以考虑在这里做一些经常需要更新的操作,很多应用我觉得也是在这里上传时间戳文件跟远程server做数据对比,如果时间戳不一样,则拉去数据。
终止应用程序
iOS系统本身就存在系统内存回收的机制,就是当其他App启动的内存不足的时候去终止一些应用程序,也有可能是在后台上时间未响应被终止的。因此,系统在终止之前会调用
- (void)applicationWillTerminate:(UIApplication *)application {
[self saveContext];
}
目的就是为了保留一些重要的数据,方便下次启动后的恢复,达到一种让用户感觉我的应用永远运行在后台从来没被终止过的感觉。
ViewController的生命周期
这里就简单的概述下.
-(void)viewDidAppear:(BOOL)animated{
}
-(void)viewWillAppear:(BOOL)animated{
}
以上两个方法就是用来注册和移除通知,observer之类的,因为每次这个View出现,消息都会调用这两个方法,可以达防止内存泄露。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
就是当前的vc初始化的时候,在这里可以配置自己的navi bar之类的。
结束
基本上就是这些吧,在这里简单的总结下,系统利用main run loop来管理事件循环,决定将事件交给系统哪些对象处理和如何处理。如果想要更深入的去了解这块,可以看看这个深入理解RunLoop
http://blog.ibireme.com/2015/05/18/runloop/
生命周期在我们的实践应用中使用的地方会很多,这里没有很深入的总结,因为自身的能力有限,如果大家有什么更好的,或者觉得这篇文章中有哪些地方需要更改或者添加,给我留言,欢迎指出缺点和错误。