UI基础 - UIViewController
■ 简言
1. UIViewController 负责根视图上面所有子视图的一切事物、检测设备的旋转和内存的警告的发生!其生命周期如下
当创建一个视图控制器的之后,视图控制器的根视图是 nil:如果根视图为 nil,就会马上调用 loadview 方法去加载一个根视图!如果父类 loadView 方法没有被重写,那么在父类中的 loadView 方法中就会帮我们创建一个根视图;如果重写了父类的 loadView 方法,那么我们在 loadView 方法中就必须创建一个根视图!注:loadView 方法执行完毕后紧接着执行 viewDidLoad 方法
当视图控制器的根视图出现时会先后调用 viewWillAppear: animated、viewDidAppear: animated;
当视图控制器的根视图消失时会先后调用 viewWillDisappear: animated、viewDidDisappear: animated
■ 工作原理
// - ViewController.m
1 #import "ViewController.h" 2 #import "SecondViewController.h" 3 @implementation ViewController 4 5 - (void)viewDidLoad { 6 [super viewDidLoad]; 7 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 8 9 UIButton *nextBT = [UIButton buttonWithType:UIButtonTypeCustom]; 10 nextBT.frame = CGRectMake(40, 80, self.view.frame.size.width - 80, 40); 11 [nextBT setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; 12 nextBT.backgroundColor = [UIColor cyanColor]; 13 nextBT.layer.masksToBounds = YES; 14 nextBT.layer.cornerRadius = 4.0; 15 [nextBT setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted]; 16 [nextBT setTitle:@"click" forState:UIControlStateNormal]; 17 nextBT.layer.cornerRadius = 8; 18 [nextBT addTarget:self action:@selector(clickBtn) forControlEvents:UIControlEventTouchUpInside]; 19 [self.view addSubview:nextBT]; 20 21 } 22 23 // 进入下级页面 24 -(void)clickBtn{ 25 SecondViewController *sdVC = [SecondViewController new]; 26 [self.navigationController pushViewController:sdVC animated:YES]; 27 } 28 29 // 内存警告: 30 - (void)didReceiveMemoryWarning { 31 [super didReceiveMemoryWarning]; 32 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 33 34 // 如果当前页面的根视图加载过且根视图并没有呈现 35 if ([self isViewLoaded] && self.view.window == nil) { 36 self.view = nil;// 卸载根视图,释放内存 37 } 38 } 39 40 // 重写 loadView 方法 41 -(void)loadView{ 42 43 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 44 // 如果在重写的 loadView 里没有给定根视图,一旦在该方法内使用点语法 self.view,则会无终止地回调 loadView 方法,造成 crash 45 self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 46 self.view.backgroundColor = [UIColor greenColor]; 47 } 48 49 // 视图将要出现 50 - (void)viewWillAppear:(BOOL)animated{ 51 52 [super viewWillAppear:animated]; 53 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 54 } 55 56 // 视图已经出现 57 - (void)viewDidAppear:(BOOL)animated{ 58 59 [super viewDidAppear:animated]; 60 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 61 62 } 63 64 // 视图将要消失 65 - (void)viewWillDisappear:(BOOL)animated{ 66 67 [super viewWillDisappear:animated]; 68 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 69 } 70 71 // 视图已经消失 72 - (void)viewDidDisappear:(BOOL)animated{ 73 74 [super viewDidDisappear:animated]; 75 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 76 } 77 78 // 检测屏幕旋转:需要重写以下几个方法 79 // 控制手机屏幕是否允许旋转 80 -(BOOL)shouldAutorotate{ 81 return YES;// 默认 YES 82 } 83 84 // 设备支持旋转的方向 85 - (UIInterfaceOrientationMask)supportedInterfaceOrientations{ 86 87 return UIInterfaceOrientationMaskAll; 88 } 89 90 // 屏幕适配:以 iPhone 5 尺寸为例 91 -(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{ 92 93 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 94 UIView * aView = [self.view viewWithTag:100]; 95 if (size.width == 568) { 96 aView.frame = CGRectMake(0, 0, 568, 220); 97 }else if (size.width == 320){ 98 aView.frame = CGRectMake(0, 0, 320, 200); 99 } 100 } 101 102 103 // !!-----方法已弃用------!! 104 -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{ 105 // 暂停音乐、关闭视图交互等 106 107 } 108 // !!-----方法已弃用-----!! 109 -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{ 110 111 // 添加自定义动画等 112 } 113 // !!-----方法已弃用------!! 114 -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{ 115 // 播放音乐、打开视图交互等 116 117 } 118 119 @end
注:视图控制器会自动调整 view 的大小以及适应屏幕旋转,当 bounds 一旦被修改,就触发 view 的 layoutSubViews 方法,我们就可以在其中重新布局
// - SecondViewController.m
1 #import "SecondViewController.h" 2 @implementation SecondViewController 3 4 - (void)viewDidLoad { 5 6 [super viewDidLoad]; 7 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 8 } 9 10 #pragma mark - overriding_methods 11 12 // loadView 13 -(void)loadView{ 14 15 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 16 self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 17 self.view.backgroundColor = [UIColor greenColor]; 18 } 19 20 - (void)viewWillAppear:(BOOL)animated{ 21 [super viewWillAppear:animated]; 22 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 23 } 24 25 26 - (void)viewDidAppear:(BOOL)animated{ 27 [super viewDidAppear:animated]; 28 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 29 30 } 31 32 - (void)viewWillDisappear:(BOOL)animated{ 33 [super viewWillDisappear:animated]; 34 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 35 } 36 37 - (void)viewDidDisappear:(BOOL)animated{ 38 [super viewDidDisappear:animated]; 39 NSLog(@"%s,%d",__FUNCTION__,__LINE__); 40 } 41 42 @end
日志信息
A. 程序开始运行时
B. 进入 SecondvVewController 时
C. 返回 viewController 时
注:当我们重写了 loadView 且没有给根视图赋值,那么在 viewDidLoad 调用 self.view 会引起的崩溃,其原因很可能是苹果使用了懒加载
1 - (UIView *)view{ 2 3 if (_view == nil) { 4 [self loadView]; 5 [self viewDidLoad]; 6 } 7 return _view; 8 }
分类:
UI章节
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律