当前位置: 首页 > news >正文

[iOS] ViewController 的生命周期

文章目录

  • 前言
  • 一、UIViewController 生命周期有关函数
  • 二、UIViewController 中函数的执行顺序
    • 运行结果
      • 1.present和dismiss
      • 2.push和pop
  • 三、总结

前言

UIViewController 是在 iOS 开发中一个非常重要的角色,他是 view 和 model 的桥梁,通过 UIViewController 的管理将数据展示在视图上。与此同时作为 uikit 中最基本的一个类,一般复杂的项目都离不开 UIViewController 作为基类,所以了解 UIViewController 的生命周期是很重要的。

一、UIViewController 生命周期有关函数

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

请添加图片描述

二、UIViewController 中函数的执行顺序

下面我会给出代码这段代码是将两个视图之间进行转换,同时打印相关的函数名来观察他的生命周期。在这里我给了两种方式来展示出他的转换,一个是 push 一个是 present。

#import "ViewControllerA.h"
#import "ViewControllerB.h"
@interface ViewControllerA ()
@property (nonatomic, strong) UIButton *btn1;
@property (nonatomic, strong) UIButton *btn2;
@end@implementation ViewControllerA- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor blueColor];_btn1 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn1 setTitle:@"next_view" 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];_btn2 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn2 setTitle:@"next_view" forState:UIControlStateNormal];_btn2.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 + 150, 200, 100);[self.view addSubview:_btn2];[_btn2 addTarget:self action:@selector(Next_push) forControlEvents:UIControlEventTouchUpInside];NSLog(@"%s", __func__);
}
- (void) Next_present {ViewControllerB *b = [[ViewControllerB alloc] init];NSLog(@"--------a->b---------");b.modalPresentationStyle = UIModalPresentationFullScreen;[self presentViewController:b animated:YES completion:nil];
}
- (void) Next_push {ViewControllerB *b = [[ViewControllerB alloc] init];NSLog(@"--------a->b---------");[self.navigationController pushViewController:b animated:YES];
}
- (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__);
}
/*
#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
#import "ViewControllerB.h"
#import "ViewControllerA.h"
@interface ViewControllerB ()
@property (nonatomic, strong) UIButton *btn1;
@property (nonatomic, strong) UIButton *btn2;
@end@implementation ViewControllerB- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor redColor];_btn1 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn1 setTitle:@"next_dismiss" 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_dismiss) forControlEvents:UIControlEventTouchUpInside];_btn2 = [UIButton buttonWithType:UIButtonTypeSystem];[_btn2 setTitle:@"next_pop" forState:UIControlStateNormal];_btn2.frame = CGRectMake(self.view.frame.size.width / 2 - 50, self.view.frame.size.height / 2 + 150, 200, 100);[self.view addSubview:_btn2];[_btn2 addTarget:self action:@selector(Next_pop) forControlEvents:UIControlEventTouchUpInside];NSLog(@"%s", __func__);
}
- (void) Next_dismiss {NSLog(@"--------b->a---------");[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) Next_pop {NSLog(@"--------b->a---------");[self.navigationController popViewControllerAnimated:YES];
}
- (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__);
}
/*
#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

运行结果

1.present和dismiss

请添加图片描述

下面是函数打印的结果

请添加图片描述

在这里就是这样一个顺序,就是先执行loadview这一步把View载入到内存中,然后再用viewDidload这个方法把控件加载到view上,然后就是调用viewwilllayoutsubviewviewdidlayoutsubview这两个方法来进行布局,最后会执行 viewdidappear 这个方法完成所有视图的加载。

这是弹出的部分,在后面我们把 push 和 pop 这一对展示完后我会去结合 present 和 dismis解释视图消失相关的内容。

2.push和pop

请添加图片描述

代码和上面相同

下面是打印结果

请添加图片描述

在这里我去着重介绍一下他的消失顺序,push 和 pop 的消失与 present 和 dismiss 的消失最大的不同就是push 中的 viewDidDisappear 是在下一个视图的 viewDidAppear 之前的然而你像在 present 中 viewDidDisappear是在下一个视图 viewDidAppear 之后的。

在这里最重要的原因就是

  • 因为 push 是栈结构,A 被“挤下去”,所以它会走消失的生命周期。
  • B 被放在最顶上,执行“将要出现”和“已经出现”。
  • present 时,B 的 didAppear 在 A 的 didDisappear 之前执行
  • 也就是说,新控制器(B)已经展示成功了,旧控制器(A)才真正被认为消失。
  • 这是因为 present 是模态展示,A 并没有被销毁,只是被 B 遮挡了,系统优先保证 B 先可见。

三、总结

init / loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear
-> viewWillDisappear -> viewDidDisappear -> dealloc

这就是一个非常简单的流程图他也展示了UIViewController 的生命周期。

在这里我想补充一点就是

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

在这之中我们必须要使用**[super loadView]**因为这样他就可以帮助我们自动生成 View。如果我们找不到 View,程序就会一直调用loadView方法来寻找。


文章转载自:

http://lzlQiCM3.trnhy.cn
http://wXjUhj2F.trnhy.cn
http://m4BqYhFQ.trnhy.cn
http://Y3SMgkKC.trnhy.cn
http://VmYHv1PP.trnhy.cn
http://E24UqIVC.trnhy.cn
http://d59hN8Lh.trnhy.cn
http://k6ST9UzN.trnhy.cn
http://PB6MjYnF.trnhy.cn
http://DUSxZtNJ.trnhy.cn
http://hV7UyszL.trnhy.cn
http://oYsxEsJg.trnhy.cn
http://7YF1LWLV.trnhy.cn
http://vJMMqlNz.trnhy.cn
http://rUpPFI6S.trnhy.cn
http://SMB7jRlV.trnhy.cn
http://B7fx5Qyn.trnhy.cn
http://CVsYAH7Z.trnhy.cn
http://m05PblQB.trnhy.cn
http://oZrdcVb4.trnhy.cn
http://a6qbTWya.trnhy.cn
http://QHKDeAkQ.trnhy.cn
http://OtOVlllS.trnhy.cn
http://7oVEzGfa.trnhy.cn
http://1mYnDwyo.trnhy.cn
http://efY2SujH.trnhy.cn
http://X65ta2pL.trnhy.cn
http://faxlEBIG.trnhy.cn
http://rT0p3MKl.trnhy.cn
http://8apJfiEW.trnhy.cn
http://www.dtcms.com/a/376429.html

相关文章:

  • MySQL 核心文件解析:从配置到存储的 “说明书 + 记录仪” 系统
  • 一文了解大模型压缩与部署
  • Jenkins 构建 Node 项目报错解析与解决——pnpm lockfile 问题实战
  • Wazuh 研究记录 | 开源XDR | 安全基线检测
  • 配电网故障诊断与自愈控制工具的智慧能源开源了
  • [邮件服务器core] 安全通信(SSL/TLS) | OpenSSL库管理 | 服务端安全SECURITY.md
  • Workers API 实战教程:45 秒完成 CI/CD 云函数部署
  • MySQL收集processlist记录的shell工具mysql_collect_processlist
  • 计算机毕业设计 基于Hadoop的健康饮食推荐系统的设计与实现 Java 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】
  • 【nginx基础】Nginx安装指南:CentOS 7.9源码编译安装Nginx 1.28.0完整指南
  • ShardingJDBC实战指南
  • 数据库--MySQL数据管理
  • Java全栈学习笔记33
  • 网络学习笔记
  • GitHub每日最火火火项目(9.10)
  • 基于stm32的环境监测系统/智能家居/空气质量监测系统
  • 基于PyQt5和阿里云TTS的语音合成应用开发实战[附源码】
  • Linux的V4L2视频框架学习笔记
  • Android studio安装教程——超详细(含安装包安装教程)
  • 如何将大型音频文件从 iPhone 发送到不同的设备
  • 使用阿里云容器镜像服务 ACR
  • ffmpeg内存模型
  • Android面试指南(八)
  • 不止是进度条:深入PiXSingleGUI的TpSlideProgressBar组件架构设计​
  • Flutter 视频播放器——flick_video_player 介绍与使用
  • 【Java】Hibernate管理Session
  • 【ARMv7】系统复位上电后的程序执行过程
  • Ubuntu引导修复
  • PetaLinux_User_udev
  • 《链表的优雅封装:C++ list 模拟实现与迭代器之美》