【iOS】UIViewController的生命周期
UIViewController的生命周期
文章目录
- UIViewController的生命周期
- 前言
- UIViewController的一个结构
- UIViewController的函数的执行顺序
- 运行代码
- viewWillAppear && viewDidAppear
- 多个视图控制器跳转时的生命周期
- push
- present
- 小结
前言
之前对于有关于UIViewControlller的理解比较浅显,仅仅只知道他是用来加载视图的,后面在有关天气预报的内容中了解了有关视图控制器生命周期的内容。
UIViewController的一个结构
UIViewController这个视图控制器
UIViewController的函数的执行顺序
这里先给出一个图片来展示一下流程,然后我们在通过讲解一下相关的内容,这里我们尝试在打印所有的内容。
这里笔者想通过两个视图控制之间相互切换来实现一个展示每一个视图控制器生命周期的效果,这里我们先讨论有关于
loadView
这个函数开始的一些执行过程。
这里我们先要重写有关ViewController的生命周期中所有函数,让他先可以打印自己的函数名。
//
// FirsttViewController.m
// ViewController的生命周期
//
// Created by nanxun on 2024/9/9.
//#import "FirsttViewController.h"
#import "TestViewController.h"
@interface FirsttViewController ()@end@implementation FirsttViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = UIColor.whiteColor;UIView* myView = [[UIView alloc] initWithFrame:CGRectMake(80, 80, 80, 80)];myView.backgroundColor = UIColor.redColor;[self.view addSubview:myView];UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];btn.frame = CGRectMake(200, 200, 50, 50);btn.backgroundColor = UIColor.redColor;[self.view addSubview:btn];[btn addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];NSLog(@"%s", __func__);// Do any additional setup after loading the view.
}
-(void)loadView {[super loadView];//注意这里重写子类方法的时候记得要先调用父类方法NSLog(@"%s", __func__);
}
-(void)press {TestViewController* vc =[[TestViewController alloc] init];[self.navigationController pushViewController:vc animated:YES];
}
-(void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];NSLog(@"%s", __func__);
}
-(void)viewDidAppear:(BOOL)animated {[super viewDidAppear:animated];NSLog(@"%s", __func__);
}
-(void)viewWillLayoutSubviews {[super viewWillLayoutSubviews];NSLog(@"%s", __func__);
}
-(void)viewDidLayoutSubviews {[super viewDidLayoutSubviews];NSLog(@"%s", __func__);
}
-(void)viewWillDisappear:(BOOL)animated {[super viewWillDisappear:animated];NSLog(@"%s", __func__);
}
-(void)viewDidDisappear:(BOOL)animated {[super viewDidDisappear:animated];NSLog(@"%s", __func__);
}
- (void)dealloc {NSLog(@"%s", __func__);
}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end
运行代码
这里我们通过打断点的方式给每一个ViewController的方法都打上断点,然后我们先加载第一个视图控制器
这里可以看到我们的代码是这样一个执行流程:先执行loadView
这一步是将view载入到内存中,然后我们在viewDidLoad
这个方法中把相关的控件加载到我们的view上,再执行ViewWillAppear
这个方法,后面会调用ViewWillLayoutSubview
这个方法,然后就会把视图布局好,然后执行ViewDidLayoutSubview
这个方法然后我们就会执行ViewDidAppear
这个方法来完成我们的所有视图的加载。
这时候我们通过点击我们的按钮然后我们这里可以看到两个视图控制器,从前一个视图控制器转移到后面的视图控制器的过程并不是前一个视图控制器直接执行viewWillDisAppear
而是后一个视图控制器先执行viewDidLoad
这个方法加载好控件之后前一个视图控制开始执行有关消失的方法,后一个视图控制器开始执行有关视图出现的函数,这样个流程才实现一个视图控制器的完整的生命周期,下面我给出打印的内容。
后面的视图控制器出现在屏幕上,和前一个视图控制器的view消失是一个交替的过程,这里可以看到我们的第一个视图控制器并没有被释放,没有执行有关视图控制器销毁的函数,但是当我们从后面的一个视图控制器跳转到前一个视图控制器的时候,后面的视图会执行一个dealloc
的销毁函数,这里指的是视图控制器的销毁。
这里笔者简单讲述分析一下每一个视图控制器调用的函数的相关作用:(引用自UIViewController的生命周期)
- 1、
initWithCoder:
或initWithNibName:Bundle
首先从归档文件中加载UIViewController
对象。即使是纯代码,也会把nil作为参数传给后者。- 2、
awakeFromNib
作为第一个方法的助手,方法处理一些额外的设置- 3、
loadView
创建或加载一个view并把它赋值给UIViewController
的view
属性- 4、
viewDidLoad
此时整个视图层次(view hierarchy
)已经放到内存中,可以移除一些视图,修改约束,加载数据等- 5、
viewWillAppear
视图加载完成,并即将显示在屏幕上。还没设置动画,可以改变当前屏幕方向或状态栏的风格等- 6、
viewWillLayoutSubviews
即将开始子视图位置布局- 7、
viewDidLayoutSubviews
用于通知视图的位置布局已经完成- 8、
viewDidAppear
视图已经展示在屏幕上,可以对视图做一些关于展示效果方面的修改。- 9、
viewWillDisappear
视图即将消失- 10、
viewDidDisappear
视图已经消失- 11、
dealloc
视图销毁的时候调用
笔者这里补充一下有关于前三个函数内容理解:
-
这里可以看到我么的第一步创建方式如果是代码的方式他会执行
initWithNibName:Bundle
这个方法,我们因为是通过纯代码方式创建的,会将nil作为一个参数传到后者。我们的另一种则是通过故事板来创建。 -
当
awakeFromNib
方法被调用时,所有视图的outlet
和action
已经连接,但还没有被确定,这个方法可以算作适合视图控制器的实例化配合一起使用的,因为有些需要根据用户喜好来进行设置的内容,无法存在storyBoard
或xib
中,所以可以在awakeFromNib
方法中被加载进来。 -
loadView
这个方法中,要正式加载View了。首先我们得知道,控制器 view 是通过懒加载的方式进行加载的,即用到的时候再加载。永远不要主动调用这个方法。当我们用到控制器 view 时,就会调用控制器 view 的 get 方法,在 get 方法内部,首先判断 view 是否已经创建,如果已存在,则直接返回存在的 view,如果不存在,则调用控制器的 loadView 方法,在控制器没有被销毁的情况下,loadView 也可能会被执行多次。- 这里提到了如果不存在view的话他会执行多次
loadView
这里可能会出现一个死循环,也就是说我们在重写的loadView
方法中没有创建view这里就会出现一个死循环的问题 - 对于是否要调用
super loadView
这个语句的话,并把子类的 view 赋给 view 属性 (property) (你 create 的 view 必须是唯一的实例,并且不被其他任何 controller 共享)。 **如果你要进行进一步初始化你的 views,你应该在 viewDidLoad 函数中去做。**在实际上我们如果想重写这个方法的时候也是要设置一个不同的子类view,而如果调用的是super loadView
这个语句的话,他只会返回一个空白的View,在开发的角度来说没有什么意义,笔者这里仅仅只是为了展示UIViewController的一个生命周期才调用上述的这个方法。
这里有图可以很好的展示相关的内容:
- 这里提到了如果不存在view的话他会执行多次
viewWillAppear && viewDidAppear
- viewWillAppear:在系统载入视图的时候,会调用这个方法,我们可以在这个方法中对将要显示的视图再进一步的设置,同时调用数据要更新的时候,都在这个方法里面实现。
- viewDidAppear: 在view被添加到视图层级中以及多视图,上下级视图切换时调用这个方法,在这里可以对正在显示的视图做进一步的设置。
视图层次(view hierachy)因为每个视图都有自己的子视图,这个视图层次其实也可以理解为一颗树状的数据结构。而树的根节点,也就是
根视图(root view)
,在UIViewController
中以view
属性。它可以看做是其他所有子视图的容器,也就是根节点。
多个视图控制器跳转时的生命周期
push
当我们点击 push 的时候首先会加载下一个界面然后才会调用界面的消失方法。
- init:ViewController2
- loadView:ViewController2
- viewDidLoad:ViewController2
- viewWillDisappear:ViewController1 将要消失
- viewWillAppear:ViewController2 将要出现
- viewWillLayoutSubviews ViewController2
- viewDidLayoutSubviews ViewController2
- viewWillLayoutSubviews:ViewController1
- viewDidLayoutSubviews:ViewController1
- viewDidDisappear:ViewController1 完全消失
- viewDidAppear:ViewController2 完全出现
上面的图片也展示出了这个过程。
push会调用我们的viewDidDisappear
方法
present
但是present方法和push调用的视图控制器的流程是不一样的:
这里发现我们的present方法并不会让我们的前一个视图控制器调用viewWillAppear
和viewDidAppear
这两个方法,同时也不会调用有关于viewDidDisappear
和viewWillDisAppear
小结
笔者对于UIViewController
的生命周期有了一点简单的认识,后面会讲一下这里push和present两个方法具体区别。
参考博客
UIViewController的生命周期
相关文章:

【iOS】UIViewController的生命周期
UIViewController的生命周期 文章目录 UIViewController的生命周期前言UIViewController的一个结构UIViewController的函数的执行顺序运行代码viewWillAppear && viewDidAppear多个视图控制器跳转时的生命周期pushpresent 小结 前言 之前对于有关于UIViewControlller的…...

ELK在Linux服务器下使用docker快速部署(超详细)
ELK是什么? 首先说说什么是ELK ELK 是一个开源的日志管理和分析平台,由三个主要组件组成: Elasticsearch:一个分布式搜索和分析引擎,能够快速存储、搜索和分析大量数据。它是 ELK 堆栈的核心,负责数据的…...

unity导入半透明webm + AE合成半透明视频
有些webm的文件导入unity后无法正常播报,踩坑好久才知道需要webm中的:VP8 标准 现在手上有几条mp4双通道的视频,当然unity中有插件是可以支持这种视频的,为了省事和代码洁癖,毅然决然要webm走到黑。 mp4导入AE合成半透…...

力扣: 四数相加II
文章目录 需求代码结尾 需求 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1: 输入…...

径向基函数神经网络RBFNN案例实操
简介 (来自ChatGPT的介绍,如有更正建议请指出) 径向基函数神经网络(Radial Basis Function Neural Network, RBFNN)是一种特殊的前馈神经网络,其结构和特点与其他常见的神经网络有所不同,主要表现在以下几个方面: 网络结构三层结构:RBF神经网络通常由三层组成:输入层…...

Java-数据结构-二叉树-习题(一) (✪ω✪)
文本目录: ❄️一、习题一(检查两颗树是否相同): ▶ 思路: ▶ 代码: ❄️二、习题二(另一棵树的子树): ▶ 思路: ▶ 代码: ❄️三、习题三(翻转二叉树): ▶ 思路: ▶ 代…...

js 时间戳转日期格式
timestampToDate(obj.project_time), import moment from “moment”; const timestampToDate (timestamp: any) > { const date new Date(timestamp * 1000); const newDate moment(date).format(“YYYY-MM-DD”); return newDate; // 使用Intl.DateTimeFormat进行格式…...

基于人工智能的自动驾驶系统项目教学指南
自动驾驶系统是人工智能的一个核心应用领域,涉及多个学科的交叉:从计算机视觉、深度学习、传感器融合到控制系统,自动驾驶项目可以提供高度的挑战性和实践意义。在这篇文章中,我们将构建一个基于深度学习的自动驾驶系统的简化版本…...

[Linux#49][UDP] 2w字详解 | socketaddr | 常用API | 实操:实现简易Udp传输
目录 套接字地址结构(sockaddr) 1.Socket API 2.sockaddr结构 3. sockaddr、sockaddr_in 和 sockaddr_un 的关系 sockaddr 结构体 sockaddr_in 结构体(IPv4 套接字地址) sockaddr_un 结构体(Unix域套接字地址&a…...

期权组合策略有什么风险?期权组合策略是什么?
今天期权懂带你了解期权组合策略有什么风险?期权组合策略是什么?期权组合策略是通过结合不同期权合约(如看涨期权和看跌期权),以及标的资产(如股票)来实现特定投资目标的策略。 期权组合策略市…...

从Zotero6到Zotero7的数据迁移尝试?(有错勿喷,多多指教!)
从Zotero6到Zotero7的数据迁移尝试 0 前言 之前在主机上一直用的Zotero6(实验室主机),最近发现在个人笔记本上看论文更频繁,尝试重新部署Zotero,才发现竟然更新了!所以这里简单记录一下数据迁移过程&…...

快速排序(分治思想)
什么是快速排序 快速排序(Quick Sort)是一种广泛使用的高效排序算法,由计算机科学家托尼霍尔在1960年提出。它采用分治法(Divide and Conquer)策略,将一个大数组分为两个小数组,然后递归地对这两…...

JAVA相关知识
JAVA基础知识 说一下对象创建的过程? 类加载检查:当Java虚拟机(JVM)遇到一个类的new指令时,它首先检查这个类是否已经被加载、链接和初始化。如果没有,JVM会通过类加载器(ClassLoaderÿ…...

详解TCP的三次握手
TCP(三次握手)是指在建立一个可靠的传输控制协议 (TCP) 连接时,客户端和服务器之间的三步交互过程。这个过程的主要目的是确保连接是可靠的、双方的发送与接收能力是正常的,并且可以开始数据传输。下面是对每个步骤的详细解释&…...

Java面试篇基础部分-Java创建线程详解
导语 多线程的方式能够在操作系统的多核配置上更好的利用服务器的多个CPU的资源,这样的操作可以使得程序运行起来更加高效。Java中多线程机制提供了在一个进程内并发去执行多个线程,并且每个线程都并行的去执行属于线程处理的自己的任务,这样可以提高程序的执行效率,让…...

Ubuntu 20.04/22.04无法连接网络(网络图标丢失、找不到网卡)的解决方案
问题复述: Ubuntu 20.04无法连接到网络,网络连接图标丢失,网络设置中无网络设置选项。 解决方案 对于Ubuntu 20.04而言:逐条执行 sudo service network-manager stopsudo rm /var/lib/NetworkManager/NetworkManager.statesudo…...

《MDTv2- Masked Diffusion Transformer is a Strong Image Synthesizer》
论文摘要 论文提出了一种名为**Masked Diffusion Transformer (MDT)**的新模型,旨在增强扩散概率模型(DPMs)在图像合成中的上下文推理能力。通过引入掩码潜在建模方案,MDT能够显著提升DPMs在图像中对象部分之间关系的学习能力&am…...

算法 - 二分查找
算法 - 二分查找 今天继续八股文学习,看一下比较常规的几个算法 二分查找是一个基于分治策略的搜索方法,简单的理解就是每次都缩小一轮搜索范围,从中间search一次,直到搜索到结果或者为空为止。 基本思路(设一个有序的…...

Python知识点:如何使用Python进行图像批处理
在Python中进行图像批处理可以使用多种库,如 Pillow、OpenCV 和 imageio。这些库可以用来执行各种图像处理任务,如调整大小、裁剪、旋转、滤镜应用等。以下是使用这些库进行图像批处理的示例。 使用 Pillow 进行图像批处理 Pillow 是一个功能强大的图像…...

数据结构实验1
实验题1:求1到n的连续整数和 题目描述 编写一个程序,对于给定的正整数n,求12…十n,采用逐个累加与(n1)/2(高斯法)两种解法。对于相同的n,给出这两种解法的求和结果和求解时间,并用相关数据进行测试。 运行代码 //实验题1:求1到n的连续整数和 #includ…...

使用Postman+JMeter进行简单的接口测试
以前每次学习接口测试都是百度,查看相关人员的实战经验,没有结合自己公司项目接口真正具体情况。 这里简单分享一下公司项目Web平台的一个查询接口,我会使用2种工具Postman和JMeter如何对同一个接口做调试。 准备工作 首先,登录公…...

基于 SpringBoot 的车辆充电桩管理系统
专业团队,咨询就送开题报告 摘 要 随着信息化时代的到来,管理系统都趋向于智能化、系统化,车辆充电桩管理系统也不例外,但目前国内仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,…...

centos7.9安装clamav教程
本章教程主要记录在centos7.9安装clamav过程。 ClamAV(Clam AntiVirus)是一个开源的防病毒软件工具,主要用于检测和消除恶意软件。它最初由 Tomasz Kojm 于 2001 年开发,并由 Cisco Systems 维护和支持。ClamAV 广泛应用于邮件网关、文件服务器和其他需要防病毒保护的环境中…...

产品经理如何转型为AI产品经理,如何理解AI产品工程化
技术领域,特别是人工智能和机器学习,其优秀模型的成功应用是一个复杂过程,它不仅要求技术本身的卓越,还须与现有解决方案竞争,这涉及到技术成熟度、成本有效性、市场接受度等多维度因素。 在这一过程中,产品经理扮演着核心角色,负责协调各方利益,确保技术能够转化为满…...

TiDB从0到1学习笔记(精华篇)
历时四个月,恭喜赵老师的《TiDB从0到1》 系列文章顺利完结,小编再次梳理一遍文稿,并附注解分享给大家。 整体架构 从 TiDB 1.0 到 8.0,TiDB 的体系结构一直在不断演进。接下来让我们一起看看整体架构的变化。 TiDB v1 TiDB v1&…...

NLP-新词挖掘
一、背景 网络领域的新词发现(挖掘)是一个非常重要的nlp课题。在处理文本对象时,非常关键的问题在于“切词”这个环节,几乎所有的后续结果都依赖第一步的切词。因此切词的准确性在很大程度上影响着后续的处理,切词结果…...

电脑录屏不求人,9月必备免费录屏软件推荐!苹果电脑可用!
在当今这个信息爆炸的时代,电脑录屏软件已经成为了我们日常工作和生活中不可或缺的工具。无论是制作教学视频、录制在线课程、游戏直播,还是创建产品演示,一个好的录屏软件都能帮助我们更高效地完成任务。市场上的录屏软件琳琅满目࿰…...

SpringMVC基于注解使用:国际化
01-国际化介绍 首先在bootstrap下载个页面 下载后把登录页面的代码粘上去 然后再登录页面代码上有些超链接需要再spring-mvc.xml里面配置下,登录页面才能正常显示 配置静态资源 国际化-根据浏览器语言国际化 现在是中文的情况,要改为英文 1.配置下属…...

工地安全帽检测系统源码分享
工地安全帽检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…...

如何为 DigitalOcean 静态路由操作员设置故障转移
静态路由操作器的主要目的是提供更大的灵活性,并在 Kubernetes 环境中控制网络流量。它使你能够根据应用程序的需求自定义路由配置,从而优化网络性能。该操作器作为 DaemonSet 部署,因此将在你的 DigitalOcean Managed Kubernetes 集群的每个…...