一、介绍

UIViewController是iOS开发中的核心控件,没有它那基本上任何功能都无法实现,虽然系统已经做了所有控件的生命维护,但是,了解它的生命周期是如何管理还是非常有必要的。网上有很多教程,别人写的始终是别人的,自己动手实践一下,理解才能更深刻,本文就来捋一遍VC的生命周期。

二、思路

通过三个VC,第1个VC是storyBoard创建的,第2个VC是纯code创建的,第3个是xib创建的。分别称为BoardInitViewController、CodeInitViewController、XibInitViewController,这三个控制器采用导航模式进行交互,现在在VC中把所有跟初始化相关的方法都实现一下并做打印,如下:

BoardInitViewController:

//
// BoardInitViewController.m
// 声明周期
//
// Created by 夏远全 on 2019/11/3.
// Copyright © 2019 Beijing Huayue Education Technology Co., Ltd. All rights reserved.
// #import "BoardInitViewController.h"
#import "CodeInitViewController.h" @interface BoardInitViewController () @end @implementation BoardInitViewController +(void)load {
[super load];
NSLog(@"boardVc---------%s",__func__);
} +(void)initialize {
[super initialize];
NSLog(@"boardVc---------%s",__func__);
} +(instancetype)alloc {
NSLog(@"boardVc---------%s",__func__);
return [super alloc];
} - (nullable instancetype)initWithCoder:(NSCoder *)coder {
NSLog(@"boardVc---------%s",__func__);
return [super initWithCoder:coder];
} - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil {
NSLog(@"boardVc---------%s",__func__);
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
} -(instancetype)init {
NSLog(@"boardVc---------%s",__func__);
return [super init];
} - (void)loadView {
[super loadView];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.title = @"boardVc";
NSLog(@"boardVc---------%s",__func__);
} - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"boardVc---------%s",__func__);
} - (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"boardVc---------%s",__func__);
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"boardVc---------%s",__func__);
} -(void)dealloc {
NSLog(@"boardVc---------%s",__func__);
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { CodeInitViewController *codeVc = [[CodeInitViewController alloc] init];
[self.navigationController pushViewController:codeVc animated:YES];
} @end

CodeInitViewController:

//
// CodeInitViewController.m
// 声明周期
//
// Created by 夏远全 on 2019/11/3.
// Copyright © 2019 Beijing Huayue Education Technology Co., Ltd. All rights reserved.
// #import "CodeInitViewController.h"
#import "XibInitViewController.h" @interface CodeInitViewController () @end @implementation CodeInitViewController +(void)load {
[super load];
NSLog(@"codeVc---------%s",__func__);
} +(void)initialize {
[super initialize];
NSLog(@"codeVc---------%s",__func__);
} +(instancetype)alloc {
NSLog(@"codeVc---------%s",__func__);
return [super alloc];
} - (nullable instancetype)initWithCoder:(NSCoder *)coder {
NSLog(@"codeVc---------%s",__func__);
return [super initWithCoder:coder];
} - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil {
NSLog(@"codeVc---------%s",__func__);
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
} -(instancetype)init {
NSLog(@"codeVc---------%s",__func__);
return [super init];
} - (void)loadView {
[super loadView];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.title = @"codeVc";
NSLog(@"codeVc---------%s",__func__);
} - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"codeVc---------%s",__func__);
} - (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"codeVc---------%s",__func__);
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"codeVc---------%s",__func__);
} -(void)dealloc {
NSLog(@"codeVc---------%s",__func__);
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //通过xib创建
XibInitViewController *xibVc = [[XibInitViewController alloc] init];
[self.navigationController pushViewController:xibVc animated:YES];
} @end

XibInitViewController:

//
// XibInitViewController.m
// 声明周期
//
// Created by 夏远全 on 2019/11/3.
// Copyright © 2019 Beijing Huayue Education Technology Co., Ltd. All rights reserved.
// #import "XibInitViewController.h" @interface XibInitViewController () @end @implementation XibInitViewController +(void)load {
[super load];
NSLog(@"xibVc---------%s",__func__);
} +(void)initialize {
[super initialize];
NSLog(@"xibVc---------%s",__func__);
} +(instancetype)alloc {
NSLog(@"xibVc---------%s",__func__);
return [super alloc];
} - (nullable instancetype)initWithCoder:(NSCoder *)coder {
NSLog(@"xibVc---------%s",__func__);
return [super initWithCoder:coder];
} - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil {
NSLog(@"xibVc---------%s",__func__);
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
} -(instancetype)init {
NSLog(@"xibVc---------%s",__func__);
return [super init];
} - (void)loadView {
[super loadView];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
self.title = @"xibVc";
NSLog(@"xibVc---------%s",__func__);
} - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"xibVc---------%s",__func__);
} - (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"xibVc---------%s",__func__);
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"xibVc---------%s",__func__);
} -(void)dealloc {
NSLog(@"xibVc---------%s",__func__);
} @end

三、注解

 +load: 程序启动后,在系统的main函数调用之前,系统就会加载所有的load方法,提前进行一些资源包的配置或者hook,(可以打断点看看结果,本人亲测过)

 +initialize: 当前类或者其子类未被初始化过时会首次调用,若以后当前类或者子类再多次初始化时不会再调用,一般提前为初始化做一些工作

 +alloc: 系统为当前类分配内存时调用,在C语言中就是malloc这一步

 -initWithCoder: 通过storyBoard方式实例化的vc,需要经过反序列化,这个方法会被调用

 -initWithNibName:bundle: 通过xib文件或者init方法实例化的vc,这个方法都会被调用,其实init方法最终都会走该方法

 -init: 通过纯代码实例化Vc会调用,其最终会调用initWithNibName:bundle:方法

 -loadView: 实例化Vc后,可以加载一些系统常规的View

 -viewDidLoad: 一般加载自定义的view或者初始化属性,视图加载完毕后会调用

 -viewWillAppear: 视图即将出现会调用

 -viewWillDisappear: 视图即将消失会调用

 -viewWillLayoutSubviews: 视图加载完毕后即将要布局

 -viewDidLayoutSubviews: 视图加载完毕后布局也完成了

 -didReceiveMemoryWarning: 加载视图时,内存消耗太大,出现内存警告,会调用

 -dealloc: 实例化被销毁,进行内存的回收会调用

四、演示

[1] 程序启动,加载storyBoard实例化BoardInitViewController

-- ::45.724860+ 声明周期[:] codeVc---------+[CodeInitViewController load]
-- ::45.725520+ 声明周期[:] boardVc---------+[BoardInitViewController load]
-- ::45.725713+ 声明周期[:] xibVc---------+[XibInitViewController load]
-- ::45.875841+ 声明周期[:] boardVc---------+[BoardInitViewController initialize]
-- ::45.876016+ 声明周期[:] boardVc---------+[BoardInitViewController alloc]
-- ::45.876132+ 声明周期[:] boardVc----------[BoardInitViewController initWithCoder:]
-- ::45.932805+ 声明周期[:] boardVc----------[BoardInitViewController loadView]
-- ::45.935257+ 声明周期[:] boardVc----------[BoardInitViewController viewDidLoad]
-- ::45.935932+ 声明周期[:] boardVc----------[BoardInitViewController viewWillAppear:]
-- ::45.938655+ 声明周期[:] boardVc----------[BoardInitViewController viewWillLayoutSubviews]
-- ::45.938840+ 声明周期[:] boardVc----------[BoardInitViewController viewDidLayoutSubviews]
-- ::45.960117+ 声明周期[:] boardVc----------[BoardInitViewController viewDidAppear:]

[2]  从BoardInitViewController中push到纯代码实例化的CodeInitViewController中

-- ::21.027613+ 声明周期[:] codeVc---------+[CodeInitViewController initialize]
-- ::21.027858+ 声明周期[:] codeVc---------+[CodeInitViewController alloc]
-- ::21.027986+ 声明周期[:] codeVc----------[CodeInitViewController init]
-- ::21.028089+ 声明周期[:] codeVc----------[CodeInitViewController initWithNibName:bundle:]
-- ::21.032537+ 声明周期[:] codeVc----------[CodeInitViewController loadView]
-- ::21.032821+ 声明周期[:] codeVc----------[CodeInitViewController viewDidLoad]
-- ::21.032967+ 声明周期[:] boardVc----------[BoardInitViewController viewWillDisappear:]
-- ::21.033095+ 声明周期[:] codeVc----------[CodeInitViewController viewWillAppear:]
-- ::21.054149+ 声明周期[:] codeVc----------[CodeInitViewController viewWillLayoutSubviews]
-- ::21.054325+ 声明周期[:] codeVc----------[CodeInitViewController viewDidLayoutSubviews]
-- ::21.581912+ 声明周期[:] boardVc----------[BoardInitViewController viewDidDisappear:]
-- ::21.582262+ 声明周期[:] codeVc----------[CodeInitViewController viewDidAppear:]

[3]  从CodeInitViewController中push到Xib实例化的XibInitViewController中

-- ::12.506639+ 声明周期[:] codeVc---------+[CodeInitViewController alloc]
-- ::12.506831+ 声明周期[:] codeVc----------[CodeInitViewController init]
-- ::12.507020+ 声明周期[:] codeVc----------[CodeInitViewController initWithNibName:bundle:]
-- ::12.508456+ 声明周期[:] codeVc----------[CodeInitViewController loadView]
-- ::12.509038+ 声明周期[:] codeVc----------[CodeInitViewController viewDidLoad]
-- ::12.509353+ 声明周期[:] boardVc----------[BoardInitViewController viewWillDisappear:]
-- ::12.509780+ 声明周期[:] codeVc----------[CodeInitViewController viewWillAppear:]
-- ::12.520785+ 声明周期[:] codeVc----------[CodeInitViewController viewWillLayoutSubviews]
-- ::12.521002+ 声明周期[:] codeVc----------[CodeInitViewController viewDidLayoutSubviews]
-- ::13.023817+ 声明周期[:] boardVc----------[BoardInitViewController viewDidDisappear:]
-- ::13.024016+ 声明周期[:] codeVc----------[CodeInitViewController viewDidAppear:]

[4]  将XibInitViewController进行Pop后

-- ::55.287065+ 声明周期[:] xibVc----------[XibInitViewController viewWillDisappear:]
-- ::55.287238+ 声明周期[:] codeVc----------[CodeInitViewController viewWillAppear:]
-- ::55.803065+ 声明周期[:] xibVc----------[XibInitViewController viewDidDisappear:]
-- ::55.803504+ 声明周期[:] codeVc----------[CodeInitViewController viewDidAppear:]
-- ::55.803857+ 声明周期[:] xibVc----------[XibInitViewController dealloc]

[5] 将CodeInitViewController进行Pop后

-- ::07.038091+ 声明周期[:] codeVc----------[CodeInitViewController viewWillDisappear:]
-- ::07.038281+ 声明周期[:] boardVc----------[BoardInitViewController viewWillAppear:]
-- ::07.543910+ 声明周期[:] codeVc----------[CodeInitViewController viewDidDisappear:]
-- ::07.544089+ 声明周期[:] boardVc----------[BoardInitViewController viewDidAppear:]
-- ::07.544236+ 声明周期[:] codeVc----------[CodeInitViewController dealloc]

四、总结

  • 程序一启动,系统在当前应用程序的所有方法被调用之前优先加载load方法;
  • 控制器生命的正常流程是:初始化--->加载视图--->将要显示---->布局子视图---->完全显示---->将要显示---->完全消失----->对象销毁(有可能内存警告释放)
  • 控制器交互的前后显隐流程是交叉的,在源VC即将消失和目的VC即将显示之后,目的VC会完成所有子视图的布局,然后源VC才会真正消失目的VC真正显示
  • 控制器交互消失的流程也是交叉的,目的VC即将消失,源VC即将显示,目的VC完全消失,源VC完全显示,接着释放目的VC
  • 通过stroyBoard创建的VC一定需要反序列化
  • 通过纯代码和xib创建的VC,最终都会调用initWithNibName:bundle:方法

iOS:从头捋一遍VC的生命周期的更多相关文章

  1. iOS:捋一遍View的生命周期

    一.介绍 前面介绍了VC的生命周期,闲着没事也来捋一捋View的生命周期,简单用两个类型的View来监测.一个View纯代码创建,另一个View使用Xib创建. 二 .代码 MyCodeView:  ...

  2. iOS系列 基础篇 03 探究应用生命周期

    iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...

  3. iOS系列 基础篇 04 探究视图生命周期

    iOS系列 基础篇 04 探究视图生命周期 视图是应用的一个重要的组成部份,功能的实现与其息息相关,而视图控制器控制着视图,其重要性在整个应用中不言而喻. 以视图的四种状态为基础,我们来系统了解一下视 ...

  4. QF——iOS程序运行原理(APP的生命周期)

    iOS程序的运行原理: main.m: 1. main.m 主函数是所有程序的入口函数. 2. 在main函数里是UIApplicationMain函数,开启了一个无限循环,以监听该应用. 该UIAp ...

  5. AIR Native Extension for iOS 接入第三方sdk 如何实现 AppDelegate 生命周期

    作者:Panda Fang 出处:http://www.cnblogs.com/lonkiss/p/6492385.html 原创文章,转载请注明作者和出处,未经允许不可用于商业营利活动 去年到今年做 ...

  6. iOS程序执行顺序和UIViewController 的生命周期(整理)

    说明:此文是自己的总结笔记,主要参考: iOS程序的启动执行顺序 AppDelegate 及 UIViewController 的生命周期 UIView的生命周期 言叶之庭.jpeg 一. iOS程序 ...

  7. iOS viewController 和 view 的创建消失生命周期总结

    控制器创建的生命周期 1. 如果从stroryBoard 中产生一个controller,那么会先调用initWithCoder:, awakeFromNib, loadView,viewDidLoa ...

  8. ios开发之--VC的生命周期

    当一个视图控制器被创建,并在屏幕上显示的时候. 代码的执行顺序 1. alloc                                   创建对象,分配空间 2.init (initWit ...

  9. 故事板(Storyboard) 、 iPad编程 、 App和VC的生命周期

    1 创建动态TableView 1.1 问题 动态表视图就是显示多少分区,多少行以及每一行的显示内容都是根据数据源来决定.之前我们学过用xib展示动态表视图,本案例将学习如何使用Storyboard展 ...

随机推荐

  1. Android几种多渠道打包

    1.什么是多渠道打包 在不同的应用市场可能有不同的统计需求,需要为每个应用市场发布一个安装包,这里就引出了Android的多渠道打包.在安装包中添加不同的标识,以此区分各个渠道,方便统计app在市场的 ...

  2. JEB 无源码调试 以dvm smali字节码方式,Demo尝试

    关于调试器看不到进程,无法attach的问题,网上也有很多教程,基本是修改ro.debugable =1  ,ro.secure = 0 让adbd有root权限 attach到其他进程,涉及到要修改 ...

  3. golang.org 安装脚本

    #!/usr/bin/env bash cd $GOPATH; #创建 $GOPATH/src/golang.org/x 目录 mkdir -p $GOPATH/src/golang.org/x; e ...

  4. MySQL 8.0部分弃用的参数整理

    最近整理了一下MySQL 8.0的自动化安装,其中用到了一个MySQL 5.7版本的自定义配置文件,由于没有对(MySQL 8.0)做针对性修改,导致安装过程中出现了一些错误其中部分原因就是MySQL ...

  5. jQuery - 拦截所有Ajax请求(统一处理超时、返回结果、错误状态码 )

    样例代码: <html> <head> <title>hangge.com</title> <meta charset="utf-8&q ...

  6. CodeForces-1265E(期望)

    题意 有1~n镜子,每个镜子说你漂亮的概率是pi/100,如果第i个回答你漂亮那么就一直问到第n个说漂亮为止,否则重新从1开始问,一天只问一个镜子,问直到镜子n说你漂亮的期望天数. 思路 设Ei为问到 ...

  7. HashMap、HashTable 和 ConcurrentHashMap 线程安全问题

    一.HashMap HashMap 是线程不安全的. JDK 1.7 HashMap 采用数组 + 链表的数据结构,多线程背景下,在数组扩容的时候,存在 Entry 链死循环和数据丢失问题. JDK ...

  8. 使用ping网络工具编写Shell脚本程序实现网络连接故障初步排查

    在学习ping命令的时候,突发奇想:为何不使用ping命令对网络连接故障进行排查? 具体思路: 1. ping  127.0.0.1 (虚拟网卡地址)以检查主机的TCP/IP协议栈是否正常. 2. p ...

  9. IDEA 护眼色设置

    首先做一些简单的记录,护眼色 等等的设置很久以前机器上已经设置过了,今天偶尔要在其他机器上重新做一些设置反而忘记了很多步骤, 设置后的HTML页面如下图所示: 默认情况下,当只是设置General通用 ...

  10. 拥抱webpack4,有效缩减构建时间57%+

    背景 最近有感觉到,随着系统模块数量的增加,wepack编译打包的速度越来越慢,于是我想给项目做一下优化升级,也借此机会系统地学习一下webpack4. 升级过程 当前版本 "depende ...