IOS 初级开发入门教程(三)探究应用及视图的生命周期变化
导读
操作系统都会根据应用的生命周期状态来管理和处理逻辑,这一点在Android开发上现的就已经非常好了,耳熟能详的就是应用状态影响内存回收级别和活动的生命周期。同样,在IOS上也会充分利用应用的视图的生命周期来进行管理应用。首先,我们先知道IOS应用在程序中的五种状态及其变化,然后再去看IOS工程中有一个AppDelegate的类来动手验证,它是应用程序的委托对象,(类似Android工程里重写Application类)在应用程序生命周期的不同阶段会回调不同的方法。
系列文章:
一、介绍应用生命周期
1、下列图表概括,IOS应用的五种生命状态 。
状态名称 | 状态释义 | 状态描述 |
Not running |
非活动状态 | 应用没有运行或被系统终止。 |
Inactive |
前台非活动状态 |
应用正在进入前台状态,但是还不能接受事件处理。 |
Active | 前台活动状态 | 应用进入前台状态,能接受事件处理。 |
Background | 后台状态 | 应用进入后台后,依然能执行代码。如果有可执行的代码,就会执行代码,如果没有可执 行的代码或者将可执行的代码执行完毕,应用会马上进入挂起状态。 |
Suspended | 挂起状态 | 应用处于挂起状态,不能执行代码。若系统内存不够,应用会被终止。 |
(注:这个图表比较关键,务必熟背,且关键描述字)
2、利用思维导图的方式,表示出IOS应用程序在前台、后台状态转变、生命周期的流程。
二、使用AppDelegate类回调方法监听
1、图片展示 AppDelegate 类 的回调方法,可用日志打印验证应用生命周期状态的变化。(代码在下面)
*补充:常用的打印NSLog格式如下。(可忽略)
- %@ 对象
- %d, %i 整数
- %hi 短整型
- %lli 长整型
- %u 无符整形
- %f 浮点/双字
- %0.2f 精度浮点数,且只保留两位小数
- %x, %X 二进制整数
- %o 八进制整数
- %zu size_t
- %p 指针
- %e 浮点/双字 (科学计算)
- %g 浮点/双字 科学技术法(用最简短的方式)
- %s C (char*)字符串
- %.*s Pascal字符串
- %c 字符
- %C unichar
- %lld 64位长整数(long long)
- %llu 无符64位长整数
- %Lf 64位双字
- %lu sizeof(i)内存中所占字节数
2、代码。标注AppDelegate类中各回调方法意义和作用介绍。
- // Created by aiyang on 2018/1/25.
- // Copyright © 2018年 aiyang. All rights reserved.
- #import "AppDelegate.h"
- @interface AppDelegate ()
- @end
- @implementation AppDelegate
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- //应用启动并进行初始化时会调用该方法。这个阶段会实例化根视图控制器。
- NSLog(@"%s", "application:didFinishLaunchingWithOptions: Not runing -> Inactive");
- return YES;
- }
- - (void)applicationDidBecomeActive:(UIApplication *)application {
- //应用进入前台非活动状态时调用该方法。这个阶段可以恢复UI的状态。
- NSLog(@"%s","applicationDidBecomeActive: Inactive -> active");
- }
- - (void)applicationWillResignActive:(UIApplication *)application {
- //应用从活动状态进入到非活动状态时调用该方法。这个阶段可以保存UI的状态。
- NSLog(@"%s", "applicationWillResignActive: active -> Inactive");
- }
- - (void)applicationDidEnterBackground:(UIApplication *)application {
- //应用进入后台或挂起时调用该方法。这个阶段可以保存用户数据,释放一些资源(例如释放数据库资源等)。
- NSLog(@"%s","applicationDidEnterBackground: Background -> Suspended");
- }
- - (void)applicationWillEnterForeground:(UIApplication *)application {
- //应用从后台再次回到前台,但是还没有处于活动状态时调用该方法。这个阶段可以恢复用户数据。
- NSLog(@"%s","applicationWillEnterForeground: Suspended -> Background -> Inactive");
- }
- - (void)applicationWillTerminate:(UIApplication *)application {
- //应用被终止时调用该方法,但内存清除时除外。 这个阶段释放一些资源,也可以保存用户数据。
- NSLog(@"%s","applicationWillTerminate: Suspended -> Not runing");
- }
- @end
三、动手实践-点击Home键
看到这里,不得不再次提醒,前面内容很简单、很基础、也很重要,是ios开发者必知必背的知识。如果已经看懂了,但是还记不太牢固,那么就跟着这个小练习看一遍来加深印象。
练习题:点击Home键,查看应用声明周期变化。
首先,我们要知道工程目录有一个 Info.plist 文件,其中属性 Application does not run in background 可以控制应用后台运行。如果找到不该属性,可以通过Source Code XML形式自行写入。将下面一条复制过去即可。
- //设置支持后台运行
- <key>UIApplicationExitsOnSuspend</key>
- <false/>
- //设置不支持后台运行
- <key>UIApplicationExitsOnSuspend</key>
- <true/>
配置参数文件 info.plist ->Open As 有两个选项:Property List ,可视化列表形式(默认),Source Code 是XML形式。
然后,我们这里先设置支持后台运行,查看打印结果:
- TabbedApp[22498:1105773] application:didFinishLaunchingWithOptions: Not runing -> Inactive
- TabbedApp[22498:1105773] applicationDidBecomeActive: Inactive -> active
- TabbedApp[22498:1105773] applicationWillResignActive: active -> Inactive
- TabbedApp[22498:1105773] applicationDidEnterBackground: Background -> Suspended
- TabbedApp[22528:1107473] application:didFinishLaunchingWithOptions: Not runing -> Inactive
- TabbedApp[22528:1107473] applicationDidBecomeActive: Inactive -> active
- TabbedApp[22528:1107473] applicationWillResignActive: active -> Inactive
- TabbedApp[22528:1107473] applicationDidEnterBackground: Background -> Suspended
- TabbedApp[22528:1107473] applicationWillTerminate: Suspended -> Not runing
四、视图的生命周期
五、动手实践-切换视图监听
这次,我们动手去查验视图的生命周期变化。这里,拿上一章有一个小练习‘Tab切换’的工程拿来实践。
没有写过的小伙伴,可以先去查阅第一个HelloWorld工程及StoryBoard使用或动手创建一个新工程。
图片只是单纯展示,创建默认工程,就这个样子。有两个.m的视图文件。(图上红线没有信息,可忽略)
然后,我们点击FirstViewController.m 、SecondViewController.m ,把生命周期回调函数写上并打印日志输出。如下:
- // Created by aiyang on 2018/1/25.
- // Copyright © 2018年 aiyang. All rights reserved.
- #import "FirstViewController.h"
- @interface FirstViewController ()
- @end
- @implementation FirstViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- // 在视图控制器已被实例化,视图被加载到内存中时,会调用viewDidLoad方法,这时视图并未出现。通常会对所控制的视图进行初始化处理。
- NSLog(@"%s", "FirstView 视图创建 :viewDidLoad");
- }
- - (void)viewWillAppear:(BOOL)animated{
- NSLog(@"%s", "FirstView 视图可见 :viewWillAppear");
- }
- -(void)viewDidAppear:(BOOL)animated{
- NSLog(@"%s", "FirstView 视图可见 :viewDidAppear");
- }
- -(void)viewDidDisappear:(BOOL)animated{
- [super viewDidDisappear:animated];
- NSLog(@"%s", "FirstView 视图不可见 :viewDidDisappear");
- }
- -(void)viewWillDisappear:(BOOL)animated{
- NSLog(@"%s", "FirstView 视图不可见 :viewWillDisappear");
- }
- - (void)didReceiveMemoryWarning {
- // 释放内存,包括视图控制器中的一些成员变量和视图的释放。
- NSLog(@"%s", "FirstView 系统低内存 :didReceiveMemoryWarning");
- [super didReceiveMemoryWarning];
- }
- -(void)viewDidUnload{
- NSLog(@"%s", "FirstView 系统低内存 :viewDidUnload");
- [super viewDidUnload];
- }
- @end
- // Created by aiyang on 2018/1/25.
- // Copyright © 2018年 aiyang. All rights reserved.
- #import "SecondViewController.h"
- @interface SecondViewController ()
- @end
- @implementation SecondViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- // 在视图控制器已被实例化,视图被加载到内存中时,会调用viewDidLoad方法,这时视图并未出现。通常会对所控制的视图进行初始化处理。
- NSLog(@"%s", "SecondView 视图创建 :viewDidLoad");
- }
- - (void)viewWillAppear:(BOOL)animated{
- NSLog(@"%s", "SecondView 视图可见 :viewWillAppear");
- }
- -(void)viewDidAppear:(BOOL)animated{
- NSLog(@"%s", "SecondView 视图可见 :viewDidAppear");
- }
- -(void)viewDidDisappear:(BOOL)animated{
- [super viewDidDisappear:animated];
- NSLog(@"%s", "SecondView 视图不可见 :viewDidDisappear");
- }
- -(void)viewWillDisappear:(BOOL)animated{
- NSLog(@"%s", "SecondView 视图不可见 :viewWillDisappear");
- }
- - (void)didReceiveMemoryWarning {
- // 释放内存,包括视图控制器中的一些成员变量和视图的释放。
- NSLog(@"%s", "SecondView 系统低内存 :didReceiveMemoryWarning");
- [super didReceiveMemoryWarning];
- }
- -(void)viewDidUnload{
- NSLog(@"%s", "SecondView 系统低内存 :viewDidUnload");
- [super viewDidUnload];
- }
- @end
- TabbedApp[23162:1145440] application:didFinishLaunchingWithOptions: Not runing -> Inactive
- TabbedApp[23162:1145440] FirstView 视图创建 :viewDidLoad
- TabbedApp[23162:1145440] FirstView 视图可见 :viewWillAppear
- TabbedApp[23162:1145440] FirstView 视图可见 :viewDidAppear
- TabbedApp[23162:1145440] applicationDidBecomeActive: Inactive -> active
页面切换后,可见 第二次打印结果:
- TabbedApp[23208:1148352] SecondView 视图创建 :viewDidLoad
- TabbedApp[23208:1148352] SecondView 视图可见 :viewWillAppear
- TabbedApp[23208:1148352] FirstView 视图不可见 :viewWillDisappear
- TabbedApp[23208:1148352] FirstView 视图不可见 :viewDidDisappear
- TabbedApp[23208:1148352] SecondView 视图可见 :viewDidAppear
- TabbedApp[23208:1148352] FirstView 视图可见 : viewWillAppear
- TabbedApp[23208:1148352] SecondView 视图不可见 :viewWillDisappear
- TabbedApp[23208:1148352] SecondView 视图不可见 :viewDidDisappear
- TabbedApp[23208:1148352] FirstView 视图可见 : viewDidAppear
六、结尾,送句话。
到这里,相信小伙伴们应该已经掌握了IOS应用程序及视图的生命周期的变化了。这个是非常基础也非常重要,在日常开发中会经常用到它们去做代码逻辑处理及资源数据保存及释放。