文章目录
前言ViewController执行过程的探讨ViewControllerOne
函数介绍顺序引入ViewControllerSecond引入
ViewControllerOne点击执行到ViewControllerSecond的2种情况View加载的分析Viewdidload之后发生地事情viewWillAppear 和 viewDidAppear 中间的过程
viewWillDisappear 和 viewDidDisappear
结尾
前言
在写项目的时候,ViewController是最基本的东西,只是知道他用来加载视图,控件的全能函数,把一些控件啥的不管都写在里面去了,通过了解ViewController的生命周期发现他的内部存在许多函数
ViewController执行过程的探讨
思路:设置2个界面,采用P resent同级跳转的方法推出界面,之后在第二界面设置返回Button,每个界面的每个函数打印操作过程就能看到先后顺序了代码
ViewControllerOne
先进行一下ViewControllerOne的初始化加载,函数放到后面去讲,和平常不一样的是打印了每个函数执行过程
#import
NS_ASSUME_NONNULL_BEGIN
@interface ViewControllerSecond : UIViewController
// Button跳转到下一界面
@property (nonatomic, strong)UIButton* buttonReturn;
@end
NS_ASSUME_NONNULL_END
#import "ViewControllerSecond.h"
#import "Masonry.h"
@interface ViewControllerSecond ()
@end
@implementation ViewControllerSecond
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%s",__func__);
self.view.backgroundColor = [UIColor orangeColor];
_buttonReturn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_buttonReturn setTitle:@"Return" forState:UIControlStateNormal];
[_buttonReturn addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_buttonReturn];
[_buttonReturn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_offset(150);
make.left.mas_offset(200);
make.width.mas_offset(200);
make.height.mas_offset(100);
}];
}
- (void)loadView {
[super loadView];
NSLog(@"%s",__func__);
}
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewWillLayoutSubviews {
NSLog(@"%s",__func__);
}
- (void)viewWillDisappear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewDidLayoutSubviews {
NSLog(@"%s",__func__);
}
- (void)viewDidDisappear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)press {
NSLog(@"-------------Second is Back!--------------");
[self dismissViewControllerAnimated:YES completion:nil];
}
/*
#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
执行第一界面的加载
函数介绍
结果:从上到下一次打印了VIew执行过程函数viewDidLoad:在视图加载后被调用,如果是在代码中创建的视图加载器,他将会在loadView方法后被调用,如果是从nib视图页面输出,他将会在视图设置好后后被调用。只会被调用一次,之后进入这个ViewController不调用此函数loadView:每次访问controller的view(比如controller.view、self.view)且view为nil,loadView方法就会被调用。用于创建Controller的ViewviewWillAppear: 视图将要显示viewWillLayoutSubviews: 控制器的view将要布局子控件(在这个方法里,部署需要改变重新刷新view的代码,功能类似view的layoutSubViews()这个方法,需要注意的是,这个方法里一般都需要重置的view的frame,宽度和高度的获取,因此view的frame一般都写在这个方法里)viewDidLayoutSubviews: 控制器的view布局子控件完成viewDidAppear: 视图已经显示viewWillDisappear: 视图将要消失viewDidDisappear: 视图已经消失,在Controller被切换时调用,第二个视图出现后第一个视图消失
顺序引入
我们发现上述结果只打印到了DidAppear函数,并没有出现DIss appear的两个函数,如上所述,dis appear是界面即将消失的时候出现的函数,我们并没有切换界面,所以这个函数也不会调用接下来引入界面二,看diss appear的调用位置
ViewControllerSecond引入
代码
#import
NS_ASSUME_NONNULL_BEGIN
@interface ViewControllerSecond : UIViewController
// 返回第一界面的Button
@property (nonatomic, strong)UIButton* buttonReturn;
@end
NS_ASSUME_NONNULL_END
#import "ViewControllerSecond.h"
#import "Masonry.h"
@interface ViewControllerSecond ()
@end
@implementation ViewControllerSecond
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%s",__func__);
self.view.backgroundColor = [UIColor orangeColor];
_buttonReturn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_buttonReturn setTitle:@"Return" forState:UIControlStateNormal];
[_buttonReturn addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_buttonReturn];
[_buttonReturn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_offset(150);
make.left.mas_offset(200);
make.width.mas_offset(200);
make.height.mas_offset(100);
}];
}
- (void)loadView {
[super loadView];
NSLog(@"%s",__func__);
}
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewWillLayoutSubviews {
NSLog(@"%s",__func__);
}
- (void)viewWillDisappear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)viewDidLayoutSubviews {
NSLog(@"%s",__func__);
}
- (void)viewDidDisappear:(BOOL)animated {
NSLog(@"%s",__func__);
}
- (void)press {
NSLog(@"-------------Second is Back!--------------");
[self dismissViewControllerAnimated:YES completion:nil];
}
/*
#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
ViewControllerOne点击执行到ViewControllerSecond的2种情况
在这里出现2种不同的情况情况一:在第二界面加载出来的时候第一界面的dissappear并没有出现,后来发现我在第一界面的Button事件里面缺少了这句话View.modalPresentationStyle = UIModalPresentationFullScreen;的意思是弹出并且是占据了整个屏幕,接下来加上这句话- 分析:看到上述结果就是一个View加载的全部过程了,首先我们得知道,控制器 view 是通过懒加载的方式进行加载的,即用到的时候再加载。,所以系统先去loadView里执行了一遍我们重写的方法[super loadView]; 接下来再去加载View
View加载的分析
View加载的过程(转):在 view 加载过程中首先会调用 loadView 方法,在这个方法中主要完成一些关键 view 的初始化工作,比如 UINavigationViewController 和 UITabBarController 等容器类的 ViewController;接下来就是加载 view,加载成功后,会接着调用 viewDidLoad 方法,这里要记住的一点是,在 loadView 之前,是没有 view 的,也就是说,在这之前,view 还没有被初始化。完成 viewDidLoad 方法后,ViewController 里面就成功的加载 view了为此我做一尝试,在loadView函数里面不写[super loadView],结果如下,我吧Second View的load View函数改了,其他并未变化
- (void)loadView {
// [super loadView];
NSLog(@"%s",__func__);
}
直接看到,函数回去不断的重复的寻找View,也就是在loadView接下来到Viewdidload发现VIew为空,再次回去寻求View,如此重复若 loadView 没有加载 view,即为 nil,viewDidLoad 会一直调用 loadView 加载 view,因此构成了死循环,程序即卡死,所以我们常在 ViewDidLoad 里创建 view。
Viewdidload之后发生地事情
参考大佬博客UIViewController生命周期通过图片可以看到viewWillAppear总是出现在ViewdidLoad之后,但不是立即,当你只是引用了属性 view,却没有立即把 view 添加到任何已经展示的视图上时,viewWillAppear 不会被调用,这在 view 被外部引用时,就会发生。当然,随着 ViewController 的多次推入,多次进入子页面后返回,该方法会被多次调用。与 viewDidLoad 不同,调用该方法就说明控制器一定会显示。
viewWillAppear 和 viewDidAppear 中间的过程
viewWillLayoutSubviews- viewDidLayoutSubviews两个方法被调用了viewWillLayoutSubviews
该方法在通知控制器将要布局 view 的子控件时调用。每当视图的 bounds 改变,view 将调整其子控件位置。默认实现为空,可重写以在 view 布局子控件前做出改变。该方法调用时,AutoLayout 未起作用。 viewDidLayoutSubviews
该方法在通知控制器已经布局 view 的子控件时调用。默认实现为空,可重写以在 view 布局子控件后做出改变。该方法调用时,AutoLayout 未起作用。
viewWillDisappear 和 viewDidDisappear
在我们推出了视图二的时候,视图二的VIewdi dLoad函数完成了,出现了视图一的viewWillDisappear,而在视图二的ViewDidappear出现之后,视图一的viewDidDisappear才完成,也就是说在第二个界面加载开始到加载完成,第一个界面才会完全的消失!!
结尾
对于present和push只是简单的提了一下,present只是弹出,所以并么有全部的覆盖第一界面,今天主要了解UIView Controller的加载过程和生命周期,接下来会进一步学习present和push的区别
推荐链接
发表评论