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

iOS - UIViewController 生命周期

一、UIViewController 生命周期核心流程(以 iOS 13 + 为例)

先通过流程图直观理解整体顺序:

graph TD A[初始化 init] --> B[加载视图 loadView] B --> C[视图加载完成 viewDidLoad] C --> D[视图将要出现 viewWillAppear:] D --> E[视图布局更新 viewWillLayoutSubviews] E --> F[视图布局完成 viewDidLayoutSubviews] F --> G[视图已经出现 viewDidAppear:] %% 页面消失流程 G --> H[视图将要消失 viewWillDisappear:] H --> I[视图已经消失 viewDidDisappear:] %% 内存警告/销毁流程 I --> J{是否销毁?} J -->|是| K[视图卸载 viewDidUnload - 已废弃] J -->|是| L[销毁 dealloc] J -->|否| D %% 内存警告分支 C --> M[收到内存警告 didReceiveMemoryWarning] M --> N[释放非必要资源] N --> D

初始化 init

加载视图 loadView

视图加载完成 viewDidLoad

视图将要出现 viewWillAppear:

视图布局更新 viewWillLayoutSubviews

视图布局完成 viewDidLayoutSubviews

视图已经出现 viewDidAppear:

视图将要消失 viewWillDisappear:

视图已经消失 viewDidDisappear:

是否销毁?

视图卸载 viewDidUnload - 已废弃

销毁 dealloc

收到内存警告 didReceiveMemoryWarning

释放非必要资源

二、核心方法详解(新手友好版)

方法名作用 & 使用场景
init/initWithNibName:bundle:控制器初始化,仅分配内存,不要在这里创建 UI 控件(视图还没加载),适合初始化数据模型。
loadView系统自动调用,用于创建控制器的view(根视图)。⚠️ 新手注意:不要主动调用,也不要重写除非你要自定义根视图(比如用纯代码替代 xib/storyboard)。
viewDidLoad视图加载完成后调用(仅调用一次)。✅ 核心场景:创建 UI 控件、设置控件属性、网络请求初始化、数据绑定(比如给 tableView 设数据源)。
viewWillAppear:视图即将显示在屏幕上时调用(每次页面显示都会触发,比如从后台切回、跳转返回)。✅ 场景:刷新数据、设置导航栏 / 状态栏样式、开启定时器 / 监听。
viewWillLayoutSubviews视图即将布局子控件时调用(比如屏幕旋转、view 大小变化)。✅ 场景:调整控件布局(比如手动计算 frame)。
viewDidLayoutSubviews视图子控件布局完成后调用。✅ 场景:获取控件最终的 frame/size(比如 scrollView 的 contentSize)。
viewDidAppear:视图已经显示在屏幕上时调用。✅ 场景:执行动画、开始播放视频 / 音频、请求定位权限。
viewWillDisappear:视图即将从屏幕消失时调用。✅ 场景:关闭定时器、移除监听、保存数据、隐藏键盘。
viewDidDisappear:视图已经消失时调用。✅ 场景:停止网络请求、释放临时资源。
didReceiveMemoryWarning系统内存不足时调用。✅ 场景:释放缓存、图片、非必要的对象(注意不要释放正在使用的资源)。
dealloc控制器销毁时调用(ARC 自动管理)。✅ 场景:最后清理资源(比如移除所有监听、释放自定义的强引用对象)。

三、简单代码示例

objective-c

#import <UIKit/UIKit.h> @interface TestViewController : UIViewController @end @implementation TestViewController // 1. 初始化 - (instancetype)init { self = [super init]; if (self) { NSLog(@"1. 控制器初始化 init"); // 初始化数据模型 self.title = @"测试页面"; } return self; } // 2. 加载视图(一般不重写) - (void)loadView { [super loadView]; NSLog(@"2. 加载视图 loadView"); // 若自定义根视图,可在这里设置:self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; } // 3. 视图加载完成(仅一次) - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"3. 视图加载完成 viewDidLoad"); // 创建UI控件 UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; btn.frame = CGRectMake(100, 100, 200, 50); [btn setTitle:@"测试按钮" forState:UIControlStateNormal]; [self.view addSubview:btn]; } // 4. 视图即将显示 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSLog(@"4. 视图即将显示 viewWillAppear:"); // 刷新数据 self.navigationController.navigationBarHidden = NO; } // 5. 视图即将布局子控件 - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; NSLog(@"5. 视图即将布局子控件 viewWillLayoutSubviews"); } // 6. 视图布局子控件完成 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; NSLog(@"6. 视图布局子控件完成 viewDidLayoutSubviews"); // 获取控件最终尺寸 NSLog(@"按钮宽度:%f", self.view.subviews.firstObject.frame.size.width); } // 7. 视图已经显示 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; NSLog(@"7. 视图已经显示 viewDidAppear:"); // 执行动画 [UIView animateWithDuration:0.3 animations:^{ self.view.subviews.firstObject.alpha = 1.0; }]; } // 8. 视图即将消失 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; NSLog(@"8. 视图即将消失 viewWillDisappear:"); // 关闭定时器/监听 } // 9. 视图已经消失 - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; NSLog(@"9. 视图已经消失 viewDidDisappear:"); } // 10. 内存警告 - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; NSLog(@"10. 收到内存警告 didReceiveMemoryWarning"); // 释放缓存 } // 11. 销毁 - (void)dealloc { NSLog(@"11. 控制器销毁 dealloc"); // 最终清理 } @end

运行输出顺序(首次进入页面):

plaintext

1. 控制器初始化 init 2. 加载视图 loadView 3. 视图加载完成 viewDidLoad 4. 视图即将显示 viewWillAppear: 5. 视图即将布局子控件 viewWillLayoutSubviews 6. 视图布局子控件完成 viewDidLayoutSubviews 7. 视图已经显示 viewDidAppear:

返回上一页时输出

plaintext

8. 视图即将消失 viewWillDisappear: 9. 视图已经消失 viewDidDisappear: 11. 控制器销毁 dealloc

总结

  1. 核心顺序initloadViewviewDidLoadviewWillAppear:viewWillLayoutSubviewsviewDidLayoutSubviewsviewDidAppear:viewWillDisappear:viewDidDisappear:dealloc
  2. 关键区分viewDidLoad仅调用一次(适合初始化 UI),viewWillAppear:/viewDidAppear:每次显示都调用(适合刷新数据 / 执行动画)。
  3. 内存管理didReceiveMemoryWarning释放非必要资源,dealloc做最终清理,避免内存泄漏。
http://www.cnnetsun.cn/news/442391.html

相关文章:

  • Dify DOCX处理性能翻倍指南:99%的人都忽略的底层优化细节
  • .NET代码混淆终极指南:Obfuscar完整使用教程
  • VutronMusic:跨平台音乐播放器的智能管理体验
  • Obfuscar实战手册:5步打造坚不可摧的.NET代码防线
  • 数字永生争议:用IndexTTS 2.0复活逝者声音合适吗?
  • GLM-4.6V-Flash-WEB与JavaScript前端集成的方法论
  • MaterialDesignInXamlToolkit 终极指南:快速构建现代化 WPF 应用界面
  • GLM-4.6V-Flash-WEB在实时交互系统中的表现如何?
  • 2026年,别再盲目学AI了!这套90天“非编程”速成路径,专为小白设计,有人已靠它涨薪3倍(附内部学习资料)
  • image2csv终极指南:图像表格数据一键转CSV
  • 如何快速掌握TikTok数据采集:非官方API的完整实战指南
  • Dify调用描述生成接口频繁出错?3种高发场景及应对策略
  • 老年认知训练:记忆力游戏搭配AI语音互动
  • Dify触发器调试难?资深工程师教你用5个测试用例精准定位问题
  • GLM-4.6V-Flash-WEB能否替代传统OCR方案?实测告诉你答案
  • access_token频繁失效?Dify平台异常处理实战经验分享
  • GLM-4.6V-Flash-WEB在医疗影像初步筛查中的探索性应用
  • 如何正确设置Dify响应编码?,资深架构师的配置 Checklist
  • 【Dify配置优化黄金法则】:提升响应速度300%的秘密武器
  • Obsidian i18n插件深度解析:彻底告别英文插件困扰的终极解决方案
  • BiliTools AI视频总结:3分钟快速掌握B站核心内容的终极指南
  • BongoCat桌面萌宠:为数字生活注入温暖的终极伴侣
  • ComfyUI多GPU加速技术深度解析:突破显存限制的分布式计算方案
  • TikTok API深度重构指南:从零构建社交内容管理平台
  • 文档解析总卡顿?,一文掌握Dify中DOCX处理的五大优化技巧
  • 如果AI有“意识”,我们第一件事该是拔电源,还是开香槟?
  • caj2pdf:打破知网格式壁垒的专业转换工具
  • FIFA 23 Live Editor完全攻略:免费修改工具从入门到精通
  • Steamworks API拦截技术终极解析:DLC内容所有权模拟深度指南
  • 四叶草拼音输入法:打造纯净高效的中文输入新体验 [特殊字符]