【iOS开发】-UIViewController加载过程和生命周期

前言

  • 在写项目的时候,ViewController是最基本的东西,只是知道他用来加载视图,控件的全能函数,把一些控件啥的不管都写在里面去了,通过了解ViewController的生命周期发现他的内部存在许多函数

ViewController执行过程的探讨

  • 思路:设置2个界面,采用P resent同级跳转的方法推出界面,之后在第二界面设置返回Button,每个界面的每个函数打印操作过程就能看到先后顺序了
  • 代码
ViewControllerOne
  • 先进行一下ViewControllerOne的初始化加载,函数放到后面去讲,和平常不一样的是打印了每个函数执行过程
#import <UIKit/UIKit.h>

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的View
  • viewWillAppear: 视图将要显示
  • viewWillLayoutSubviews: 控制器的view将要布局子控件(在这个方法里,部署需要改变重新刷新view的代码,功能类似view的layoutSubViews()这个方法,需要注意的是,这个方法里一般都需要重置的view的frame,宽度和高度的获取,因此view的frame一般都写在这个方法里)
  • viewDidLayoutSubviews: 控制器的view布局子控件完成
  • viewDidAppear: 视图已经显示
  • viewWillDisappear: 视图将要消失
  • viewDidDisappear: 视图已经消失,在Controller被切换时调用,第二个视图出现后第一个视图消失
顺序引入
  • 我们发现上述结果只打印到了DidAppear函数,并没有出现DIss appear的两个函数,如上所述,dis appear是界面即将消失的时候出现的函数,我们并没有切换界面,所以这个函数也不会调用
  • 接下来引入界面二,看diss appear的调用位置
ViewControllerSecond引入
  • 代码
#import <UIKit/UIKit.h>

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的区别
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值