zoukankan      html  css  js  c++  java
  • 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:方法
  • 相关阅读:
    maven中文乱码问题——打包错误
    maven中文乱码问题——编译错误
    Vue.js 十五分钟入门
    Vue+SpringBoot+Mybatis的简单员工管理项目
    vue.js+boostrap最佳实践
    Chrome教程(二)使用ChromeDevTools命令菜单运行命令
    Chrome教程(一)NetWork面板分析网络请求
    Vue.js——vue-router 60分钟快速入门
    Vue.js——60分钟组件快速入门(下篇)
    Vue.js——60分钟组件快速入门(上篇)
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/11785606.html
Copyright © 2011-2022 走看看