iOS:从头捋一遍VC的生命周期

一、介绍

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
View Code

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
View Code

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
View Code

 

三、注解

 +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 

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

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

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

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

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

[4]  将XibInitViewController进行Pop后

2019-11-03 16:38:55.287065+0800 声明周期[6081:439250] xibVc----------[XibInitViewController viewWillDisappear:]
2019-11-03 16:38:55.287238+0800 声明周期[6081:439250] codeVc----------[CodeInitViewController viewWillAppear:]
2019-11-03 16:38:55.803065+0800 声明周期[6081:439250] xibVc----------[XibInitViewController viewDidDisappear:]
2019-11-03 16:38:55.803504+0800 声明周期[6081:439250] codeVc----------[CodeInitViewController viewDidAppear:]
2019-11-03 16:38:55.803857+0800 声明周期[6081:439250] xibVc----------[XibInitViewController dealloc]

[5] 将CodeInitViewController进行Pop后

2019-11-03 16:40:07.038091+0800 声明周期[6081:439250] codeVc----------[CodeInitViewController viewWillDisappear:]
2019-11-03 16:40:07.038281+0800 声明周期[6081:439250] boardVc----------[BoardInitViewController viewWillAppear:]
2019-11-03 16:40:07.543910+0800 声明周期[6081:439250] codeVc----------[CodeInitViewController viewDidDisappear:]
2019-11-03 16:40:07.544089+0800 声明周期[6081:439250] boardVc----------[BoardInitViewController viewDidAppear:]
2019-11-03 16:40:07.544236+0800 声明周期[6081:439250] codeVc----------[CodeInitViewController dealloc]

 

四、总结 

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

 

posted @ 2019-11-03 17:12  XYQ全哥  阅读(1172)  评论(0编辑  收藏  举报