【iOS】ViewController的生命周期

2023-09-14 20:36:05


前言

在iOS开发中UIViewController扮演者非常重要的角色,它是视图view和数据model的桥梁,通过UIViewController的管理有条不紊的将数据展示在视图上。作为UIKit中最基本的一个类,一般复杂的项目都离不开UIViewController作为基类。所以了解UIViewController的整个生命周期是有必要的。


一、UIViewController生命周期有关函数

以下是UIViewController生命周期方法的调用函数:

  • init(coder:) 或 init(nibName:bundle:)(根据视图的加载方式而定,可能不会同时调用)

init方法和initCoder方法相似,知识被调用的环境不一样。如果用代码初始化,会调用init方法,从nib文件或者归档(xib、storyboard)进行初始化会调用initCoder。initCoder是NSCoding协议中的方法,NSCoding是负责编码解码,归档处理的协议。

  • loadView():当View需要被展示而它却是nil时,ViewController会调用该方法。
    如果代码维护View的话需要重写此方法,使用xib维护View的话不用重写。
  • viewDidLoad():我们最常用的方法,类成员对象和变量的初始化我们都会放在这个方法中。在创建类后无论视图展现还是消失,这个方法也只会在布局是调用一次。
  • viewWillAppear():是在视图将要展现出来的时候调用。
  • viewDidAppear():方法是视图已经出现。
  • viewWillLayoutSubviews(), viewDidLayoutSubviews():这些方法用于处理视图布局的变化,通常在这里执行与布局相关的操作。viewWillLayoutSubviews()在子视图重新布局之前被调用,而viewDidLayoutSubviews()在子视图重新布局之后被调用。
  • viewWillDisappear():方法是视图即将消失。 -viewDidDisappear():视图已经消失。
  • traitCollectionDidChange()(如果视图控制器的特征集合发生变化)
  • didReceiveMemoryWarning()(如果系统内存不足)

二、执行顺序

我们用一个程序示例来看我们的执行顺序:我们创建AB两个viewcontroller,然后设置一个按钮让他们之间可以进行切换

#import "AViewController.h"
#import "BViewController.h"
@interface AViewController ()

@end

@implementation AViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    _btn1 = [UIButton buttonWithType:UIButtonTypeSystem];
    [_btn1 setTitle:@"next_push" forState:UIControlStateNormal];
    _btn1.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 - 50, 200, 100);
    [self.view addSubview:_btn1];
    [_btn1 addTarget:self action:@selector(next_present) forControlEvents:UIControlEventTouchUpInside];
        NSLog(@"%s", __func__);

}

- (void)next_present {
    BViewController *B = [[BViewController alloc] init];
    NSLog(@"---------A->B---------");
    B.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:B animated:YES completion:nil];
}

- (void)loadView {
    [super loadView];
    NSLog(@"%s", __func__);
}

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewWillLayoutSubviews {
    NSLog(@"%s", __func__);

}

- (void)viewDidLayoutSubviews {
    NSLog(@"%s", __func__);

}

- (void)viewDidAppear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewDidDisappear:(BOOL)animated {
    NSLog(@"%s", __func__);

}
@end
#import "BViewController.h"

@interface BViewController ()

@end

@implementation BViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    _btn1 = [UIButton buttonWithType:UIButtonTypeSystem];
    [_btn1 setTitle:@"present" forState:UIControlStateNormal];
    _btn1.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 - 50, 200, 100);
    [self.view addSubview:_btn1];
    [_btn1 addTarget:self action:@selector(next_present) forControlEvents:UIControlEventTouchUpInside];
        NSLog(@"%s", __func__);

}

- (void)next_present {
    NSLog(@"---------B->A---------");
    [self dismissViewControllerAnimated:YES completion:nil];
    
}

- (void)loadView {
    [super loadView];
    NSLog(@"%s", __func__);
}

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewWillLayoutSubviews {
    NSLog(@"%s", __func__);

}

- (void)viewDidLayoutSubviews {
    NSLog(@"%s", __func__);

}

- (void)viewDidAppear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"%s", __func__);

}

- (void)viewDidDisappear:(BOOL)animated {
    NSLog(@"%s", __func__);

}
@end

在这里插入图片描述
输出结果:

2023-09-15 09:24:00.429478+0800 viewcontroller[13601:419399] -[AViewController loadView]
2023-09-15 09:24:00.432183+0800 viewcontroller[13601:419399] -[AViewController viewDidLoad]
2023-09-15 09:24:00.436078+0800 viewcontroller[13601:419399] -[AViewController viewWillAppear:]
2023-09-15 09:24:00.438626+0800 viewcontroller[13601:419399] -[AViewController viewWillLayoutSubviews]
2023-09-15 09:24:00.438685+0800 viewcontroller[13601:419399] -[AViewController viewDidLayoutSubviews]
2023-09-15 09:24:00.459615+0800 viewcontroller[13601:419399] -[AViewController viewDidAppear:]
2023-09-15 09:24:01.630610+0800 viewcontroller[13601:419399] ---------A->B---------
2023-09-15 09:24:01.631055+0800 viewcontroller[13601:419399] -[BViewController loadView]
2023-09-15 09:24:01.631497+0800 viewcontroller[13601:419399] -[BViewController viewDidLoad]
2023-09-15 09:24:01.635034+0800 viewcontroller[13601:419399] -[AViewController viewWillDisappear:]
2023-09-15 09:24:01.635241+0800 viewcontroller[13601:419399] -[BViewController viewWillAppear:]
2023-09-15 09:24:01.637124+0800 viewcontroller[13601:419399] -[BViewController viewWillLayoutSubviews]
2023-09-15 09:24:01.637377+0800 viewcontroller[13601:419399] -[BViewController viewDidLayoutSubviews]
2023-09-15 09:24:02.142068+0800 viewcontroller[13601:419399] -[BViewController viewDidAppear:]
2023-09-15 09:24:02.142392+0800 viewcontroller[13601:419399] -[AViewController viewDidDisappear:]
2023-09-15 09:24:02.397591+0800 viewcontroller[13601:419399] ---------B->A---------
2023-09-15 09:24:02.400464+0800 viewcontroller[13601:419399] -[BViewController viewWillDisappear:]
2023-09-15 09:24:02.400764+0800 viewcontroller[13601:419399] -[AViewController viewWillAppear:]
2023-09-15 09:24:02.906699+0800 viewcontroller[13601:419399] -[AViewController viewDidAppear:]
2023-09-15 09:24:02.906936+0800 viewcontroller[13601:419399] -[BViewController viewDidDisappear:]
2023-09-15 09:24:03.331584+0800 viewcontroller[13601:419399] ---------A->B---------
2023-09-15 09:24:03.332027+0800 viewcontroller[13601:419399] -[BViewController loadView]
2023-09-15 09:24:03.332457+0800 viewcontroller[13601:419399] -[BViewController viewDidLoad]
2023-09-15 09:24:03.335091+0800 viewcontroller[13601:419399] -[AViewController viewWillDisappear:]
2023-09-15 09:24:03.335375+0800 viewcontroller[13601:419399] -[BViewController viewWillAppear:]
2023-09-15 09:24:03.336893+0800 viewcontroller[13601:419399] -[BViewController viewWillLayoutSubviews]
2023-09-15 09:24:03.337049+0800 viewcontroller[13601:419399] -[BViewController viewDidLayoutSubviews]
2023-09-15 09:24:03.841095+0800 viewcontroller[13601:419399] -[BViewController viewDidAppear:]
2023-09-15 09:24:03.841359+0800 viewcontroller[13601:419399] -[AViewController viewDidDisappear:]
2023-09-15 09:24:04.031338+0800 viewcontroller[13601:419399] ---------B->A---------
2023-09-15 09:24:04.033750+0800 viewcontroller[13601:419399] -[BViewController viewWillDisappear:]
2023-09-15 09:24:04.033976+0800 viewcontroller[13601:419399] -[AViewController viewWillAppear:]
2023-09-15 09:24:04.537921+0800 viewcontroller[13601:419399] -[AViewController viewDidAppear:]
2023-09-15 09:24:04.538108+0800 viewcontroller[13601:419399] -[BViewController viewDidDisappear:]

由此可以得出我们ViewController的生命周期执行顺序:

  • 当仅仅弹出单个视图控制器
loadView->didloadView->willAppear->willLayoutsubviews->didLayoutSubviews->didAppear
  • 当两个视图控制器来回切换,我们的第一个视图控制器不会直接调用disAppear函数,而是当第二个视图控制器didAppaer之后才会调用disAppear函数,反之也是如此

注意点

loadview:

每次访问UIViewController的view(比如vc.view、self.view)而且view为nil,loadView方法就会被调用。这也是为什么我们重写loadview方法时必须要加上[super loadView];,因为调用这个方法可以自动生成我们的view。如果我们找不到view,我们的程序就会一直调用loadview方法来寻找我们的view。

更多推荐

linux下使用crontab定时器,并且设置定时不执行的情况,附:项目启动遇到的一些问题和命令

打开终端,以root用户身份登录。运行以下命令打开cron任务编辑器:crontab-e如果首次编辑cron任务,会提示选择编辑器。选择你熟悉的编辑器,比如nano或vi,并打开相应的配置文件。在编辑器中,添加一行类似以下的命令来设置定时任务:关机00***shutdown-hnow重启4018***sudoshutd

《UnityShader 入门精要》 笔记01

UnityShader入门精要笔记01第二章渲染流水线2.1综述2.1.1什么是流水线2.1.2什么是渲染流水线2.2CPU和GPU之间的通信2.2.1把数据加载到显存中2.2.2设置渲染状态2.2.3调用DrawCall2.3GPU流水线2.3.1概述2.3.2顶点着色器2.3.3裁剪2.3.4屏幕映射2.3.5三角

释放创造力:生成式 AI 和 Amazon SageMaker 如何帮助企业为营销活动制作广告素材...

广告公司可以使用生成式AI和文字转图像根基模型,制作创新的广告素材和内容。在这篇文章中,我们将演示如何使用AmazonSageMaker从现有的基本图像生成新图像。这是一项完全托管式服务,用于大规模构建、训练和部署机器学习模型。采用此解决方案,企业无论规模如何,都可以比以往更快地制作新的广告素材,而且大幅降低成本。这样

全国职业技能大赛云计算--高职组赛题卷①(容器云)

全国职业技能大赛云计算--高职组赛题卷①(容器云)第二场次题目:容器云平台部署与运维任务1DockerCE及私有仓库安装任务(5分)任务2基于容器的web应用系统部署任务(15分)任务3基于容器的持续集成部署任务(15分)任务4Kubernetes容器云平台部署与运维(15分,本任务只公布考试范围,不公布赛题)需要环境

leetcode&lintcode分类刷题:图论(三、多源最小距离问题)

1、本次总结的题目通常是多个源头节点分别求解到达目标节点的最小距离,目标节点可能为多个,也可能为一个;要采用广度优先搜索的方法,但先提前入队的不是源头节点了,而是目标节点,由目标节点为基准一圈一圈的更新能够达到的“新目标”位置,每一圈更新能够达到的位置最多只会访问一次2、常见的题型会设置障碍物,在一些细节的特殊情况上,

KubeSphere 在互联网医疗行业的应用实践

作者:宇轩辞白,运维研发工程师,目前专注于云原生、Kubernetes、容器、Linux、运维自动化等领域。前言2020年我国互联网医疗企业迎来了“爆发元年”,越来越多居民在家隔离期间不方便去医院看诊,只好采取在线诊疗的手段。互联网医疗企业的迅速发展的同时,也暴露出更多的不足。互联网医疗作为医疗行业发展的趋势,对于解决

《研发效能(DevOps)工程师国家职业技术认证》工信部教考中心认证证书:塑造研发效能的黄金标准丨IDCF

随着科技的飞速发展和市场竞争的日益激烈,高素质的技术管理人才在当今社会中扮演着越来越重要的角色。特别是在信息技术领域,企业对于拥有专业技能和丰富知识的研发效能管理与技术人才的需求愈发旺盛。工业和信息化部教育与考试中心(以下简称工信部教考中心)颁发的认证证书,作为专业技能和知识水平的官方认可,其含金量在业界有着极高的认可

Spring MVC 七 - Locale 本地化

Spring各模块都支持国际化,SpringMVC也同样支持。DispatcherServlet通过LocaleResovler自动根据客户端的Locale支持国际化。request请求上来后,DispatcherServlet查找并设置LocaleResovler,我们可以通过RequestContext.getLo

【pytest】 参数化@pytest.mark.parametrize

1.创建test_parametrize.py通过@pytest.mark.parametrize方法设置参数importpytestimportmath#pytest参数化@pytest.mark.parametrize("base,exponent,expected",#参数变量名称#每个元组都是一条测试用例测试数

【计算机网络】深入理解TCP协议二(连接管理机制、WAIT_TIME、滑动窗口、流量控制、拥塞控制)

TCP协议1.连接管理机制2.再谈WAIT_TIME状态2.1理解WAIT_TIME状态2.2解决TIME_WAIT状态引起的bind失败的方法2.3监听套接字listen第二个参数介绍3.滑动窗口3.1介绍3.2丢包情况分析4.流量控制5.拥塞控制5.1介绍5.2慢启动6.捎带应答、延时应答1.连接管理机制正常情况下

Element UI 表单验证规则动态失效问题

Element版本:v2.15.3问题背景如下代码所示:有一个上传文件的input组件,在更新的时候,如果不上传文件表示不更新,如果要更新则点击「重新上传」按钮将上传组件显示出来<el-formref="form":model="form":rules="rules"label-width="80px"><!--这个字

热文推荐