【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并把它赋值给UIViewControllerview属性
  • 4、viewDidLoad 此时整个视图层次(view hierarchy)已经放到内存中,可以移除一些视图,修改约束,加载数据等
  • 5、viewWillAppear 视图加载完成,并即将显示在屏幕上。还没设置动画,可以改变当前屏幕方向或状态栏的风格等
  • 6、viewWillLayoutSubviews即将开始子视图位置布局
  • 7、viewDidLayoutSubviews用于通知视图的位置布局已经完成
  • 8、viewDidAppear视图已经展示在屏幕上,可以对视图做一些关于展示效果方面的修改。
  • 9、viewWillDisappear视图即将消失
  • 10、viewDidDisappear视图已经消失
  • 11、dealloc视图销毁的时候调用

笔者这里补充一下有关于前三个函数内容理解:

在这里插入图片描述

  • 这里可以看到我么的第一步创建方式如果是代码的方式他会执行initWithNibName:Bundle这个方法,我们因为是通过纯代码方式创建的,会将nil作为一个参数传到后者。我们的另一种则是通过故事板来创建。

  • awakeFromNib方法被调用时,所有视图的outletaction已经连接,但还没有被确定,这个方法可以算作适合视图控制器的实例化配合一起使用的,因为有些需要根据用户喜好来进行设置的内容,无法存在storyBoardxib中,所以可以在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的一个生命周期才调用上述的这个方法。

    这里有图可以很好的展示相关的内容:

    在这里插入图片描述

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方法并不会让我们的前一个视图控制器调用viewWillAppearviewDidAppear这两个方法,同时也不会调用有关于viewDidDisappearviewWillDisAppear

小结

笔者对于UIViewController的生命周期有了一点简单的认识,后面会讲一下这里push和present两个方法具体区别。
参考博客
UIViewController的生命周期

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

补:在Spring Boot 当中使用 Thymeleaf 视图解析器

补&#xff1a;在Spring Boot 当中使用 Thymeleaf 视图解析器 想要在 Spring Boot 当中使用 Thymeleaf 视图&#xff0c;就需要导入相关的 jar 依赖。在 pom.xml 文件中配置 。 <!-- 引入 thymeleaf-start ,项目会自动完成配置&#xff0c;--><dependency>…

网络操作系统项目

部署与管理Active Directory 项目基础知识 活动目录是一种由微软开发的网络服务&#xff0c;用于在网络环境中管理和组织用户、计算机和其他网络资源。它是基于目录服务的概念&#xff0c;类似于电话号码簿。 活动目录主要用于集中管理网络中的用户帐户、组织单位、计算机、打…

统一建模语言UML之类图(Class Diagram)(表示|关系|举例)

文章目录 1.UML2.Class Diagram2.1 类图的表示2.2 类间的关系2.2.1 关联2.2.2 聚合2.2.3 组合2.2.4 泛化&#xff08;继承&#xff09;2.2.5 实现&#xff08;接口实现&#xff09;2.2.6 依赖 2.3 类图的作用 参考&#xff1a;Class Diagram | Unified Modeling Language (UML)…

大数据新视界 --大数据大厂之Flink强势崛起:大数据新视界的璀璨明珠

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

electron react离线使用monaco-editor

1.安装monaco-editor/react和monaco-editor pnpm i monaco-editor/react pnpm i monaco-editor 2.引入并做monaco-editor离线配置 import Editor, { DiffEditor, useMonaco, loader } from monaco-editor/react import * as monaco from monaco-editor import editorWorke…

软考 -- 软件设计师 -- 二轮复习(3) -- 数据结构(持续更新)

软考 – 软件设计师 – 二轮复习(3) – 数据结构(持续更新) 文章目录 软考 -- 软件设计师 -- 二轮复习(3) -- 数据结构(持续更新)前言一、时间、空间复杂度二、递归式时间复杂度三、线性表四、栈五、栈和队列六、串七、朴素模式匹配八、KMP模式匹配九、数组十、矩阵十一、树、二…

HarmonyOS开发实战( Beta5.0)自定义装饰器实践规范

介绍 本示例介绍通过自定义装饰器在自定义组件中自动添加inspector (布局回调)方法并进行调用。 效果图预览 不涉及 使用说明 在自定义组件上添加自定义装饰器CallbackObserver&#xff0c;并根据参数设置对应的方法名和需要绑定的组件的ID。编译工程&#xff0c;可以根据…

四款音频剪辑软件免费使用,你更pick哪一个?

视频剪辑知随着软件的不断更新&#xff0c;入门门槛和操作难度也随之变得越来越低&#xff0c;但是依然有不少人不知道剪辑视频要用什么工具&#xff0c;作为一个视频剪辑爱好者&#xff0c;我尝试过不少编辑软件&#xff0c;今天就来跟大家分享一下四款视频剪辑软件在实际使用…

通用四期ARM架构银河麒麟桌面操作系统V10【安装、配置FTP客户端】

一、操作环境 服务端&#xff1a;银河麒麟桌面操作系统V10SP1 客户端&#xff1a;银河麒麟桌面操作系统V10SP1 二、服务端配置 注&#xff1a;以下命令均在终端执行 鼠标点击桌面右键&#xff0c;选择打开终端 操作步骤&#xff1a; 1、安装vsftpd软件&#xff1a;如果提…

深入理解TCP三次握手

在网络通信中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一个可靠的、面向连接的协议&#xff0c;它保证了数据包的顺序和完整性。为了建立一个稳定的连接&#xff0c;TCP 使用了一个被称为 三次握手&#xff08;Three-W…

滑动窗口(1)_长度最小的子数组

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 滑动窗口(1)_长度最小的子数组 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. …

一款高效、简洁的帧动画生成工具

在现代网页设计和移动应用开发中&#xff0c;帧动画是一种常见的动画实现方式&#xff0c;它通过连续显示一系列静态图片来模拟动画效果。然而&#xff0c;手动创建和管理这些帧动画图片不仅耗时费力&#xff0c;而且效率低下。为此&#xff0c;gka 应运而生&#xff0c;它是一…

Java学习Day41:骑龙救!(springMVC)

springMVC与sevlet都是对应表现层web的&#xff0c;但是越复杂的项目使用SpringMVC越方便 基于Java实现MVC模型的轻量级web框架 目标&#xff1a; 小案例&#xff1a; 1.导入依赖 spring-context: 提供 Spring 框架的核心功能&#xff0c;如依赖注入、事件发布和其他应用上…

无人机之伯努利定律

无人机的伯努利定律是解释无人机飞行原理的关键理论之一&#xff0c;它主要阐述了流体&#xff08;如空气&#xff09;在流动过程中速度与压力之间的关系。以下是对无人机伯努利定律的详细解释&#xff1a; 一、伯努利定律的基本原理 伯努利定律是流体力学中的一个基本原理&am…

【python】—— Python爬虫实战:爬取珠海市2011-2023年天气数据并保存为CSV文件

目录 目标 准备工作 爬取数据的开始时间和结束时间 爬取数据并解析 将数据转换为DataFrame并保存为CSV文件 本文将介绍如何使用Python编写一个简单的爬虫程序,以爬取珠海市2011年至2023年的天气数据,并将这些数据保存为CSV文件。我们将涉及到以下知识点: 使用r…

Word 脚注与正文之间的空行怎么删除啊?

全网都搜索不到解决方案&#xff0c;难道只有我一个人遇到这个问题了吗&#xff1f; 无语&#xff0c;。、;

Java导入、导出excel保姆级教程(附封装好的工具类)

前言 我们在日常开发中&#xff0c;一定遇到过要将数据导出为Excel的需求&#xff0c;那么怎么做呢&#xff1f;在做之前&#xff0c;我们需要思考下Excel的组成。Excel是由四个元素组成的分别是&#xff1a;WorkBook(工作簿)、Sheet(工作表)、Row(行)、Cell(单元格)&#xff…

linux入门到实操-1 Linux概述、诞生过程、发行版本,如何安装?

教程来源&#xff1a;B站视频BV1WY4y1H7d3 3天搞定Linux&#xff0c;1天搞定Shell&#xff0c;清华学神带你通关_哔哩哔哩_bilibili 整理汇总的课程内容笔记和课程资料&#xff0c;供大家学习交流下载&#xff1a;夸克网盘分享 本文内容为完整笔记的入门篇 概述部分历史内容…

使用LSTM(长短期记忆网络)模型预测股票价格的实例分析

一&#xff1a;LSTM与RNN的区别 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;架构。LSTM是为了解决传统RNN在处理长序列数据时遇到的梯度消失或梯度爆炸问题而设计的。 在传统的RNN中&#xff0c;信息通过隐藏状…

使用虚拟信用卡WildCard轻松订阅POE:全面解析平台功能与订阅方式

POE&#xff08;Platform of Engagement&#xff09;是一个由Quora推出的人工智能聊天平台&#xff0c;汇集了多个强大的AI聊天机器人&#xff0c;如GPT-4、Claude、Sage等。POE提供了一个简洁、统一的界面&#xff0c;让用户能够便捷地与不同的AI聊天模型进行互动。这种平台的…