iOS的视图生命周期原理(loadView)

简介

总结一下视图的生命周期原理,其实在开发中我们只需要知道怎么用就足以应付日常的任务了,了解一些原理可以帮助我们更灵活的应用。

目录

1、视图周期
2、loadView的设计目的
3、loadView的作用
4、控制器加载视图的流程
5、实际应用的案例

视图的生命周期验证

1、打印View的生成方法

- (void)awakeFromNib {
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

- (void)loadView {
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

//视图加载完成
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

// 视图将要显示
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

// 视图将要布局子视图
- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

//视图完成布局子视图
- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

/// 视图完成显示
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

// 视图将要消失
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

//视图已经消失
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
    
    // 判断当前视图是否已经被加载
    if (self.isViewLoaded && self.view.window == nil) {
        // 释放根视图
        self.view = nil;
    }
}

运行打印的结果:


视图出现顺序

可以看到先走了awakeFromNib,awakeFromNib是什么,顾名思义,系统从Nib加载,Nib也就是Xib,先去加载Xib的视图,然后执行loadView,然后经历了视图加载,视图即将出现,添加用户自定义的子视图,视图即将消失,已经消失这几个阶段。
视图出现之后就是我们眼睛可以看得见的东西,我们可以注意到,在viewDidLoad之前,有一个loadView,这个方法是做什么呢?

我们来验证一下:

说明:(OneViewController 关联了storyboard)

一、重新这个方法,里边使用self.view

- (void)loadView {
    self.view.backgroundColor = [UIColor redColor];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
//
}

运行发现,程序崩溃了,这是为什么???并且self.view = nil;
看崩溃断点:


错误线程

发现控制器的父类在调用view这个方法之后,子类OneViewController调用loadView这个方法,如此循环。。。为什么父类创建一个view会触发子类的loadView的方法,子类又去触发父类的方法?

再来验证二:
在这个方法里不去调用self.view

- (void)loadView {
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

运行发现,加载了storyboard 的视图出来,为什么此时不崩溃?self.view这句代码是出了什么问题?

验证三:

- (void)loadView {
    self.view = [[UIView alloc] init];
    self.view.backgroundColor = [UIColor redColor];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
//
}

运行也不崩溃,但是视图是红色的。

验证四:

- (void)loadView {
    self.view = [[UIView alloc] init];
    self.view.backgroundColor = [UIColor redColor];
    [super loadView];
    NSLog(@"%@ %s", [self class], __FUNCTION__);
//
}

运行结果是加载了storyboard 的视图出来。

根据上边几个验证,我们发现,验证一中,会死循环,是因为在loadView方法里使用到控制器的根视图view的时候,当前view是空的,当系统发现view根本不存在,内存没有它的地址的时候就会尝试去调用loadView的方法,自然就触发了子控制器的loadView, 然后在子控制器又使用了self.view,所以会形成一个死循环。通过验证三我们知道,初始化一个UIView并且赋值给self.view就会不会崩溃,到这样我们已经可以看到loadView的作用就是初始化一个view。

结论:loadView的设计目的就是创建视图控制器的根视图,是开发者创建一个控制器所有UI的基础

归纳以下几点:
1、加载一个控制器之前,系统会先在loadView方法中判断是否已经有一个View可以作为根视图
2、如果根视图被使用的时候,并且是nil的,就会尝试去创建一个view并赋值给控制器的根视图
3、原则上,你不需要去调用loadView方法,因为系统自动调用了
4、如果在代码中,你重写了loadView,一旦调用 super,会执行系统默认的加载 stroyboard 或者 xib 的工作,loadView内super之前的代码全部白写,也就是,只要你不调用super,系统就会从你自定义的View中加载出来,这时候与 stroyboard 或者 xib 无关。

问:我们已经知道,loadView的出现就是为了创建一个根视图,并且系统自动帮助我们调用了,那么,它的出现对于开发者有什么意义呢?
答:它出现的意义就是可以让开发者可以自定义根视图。例如:使用loadView方法触发nib中UIView的加载。

我们用一个流程图来总结:

加载视图流程

创建一个根视图的顺序:
1、是否有一个view可用
2、如果有,直接显示这个view;如果没有,则系统自动调用loadView方法去生成一个view
3、当重写了loadView方法,并在里边自定义了view则直接使用这个view作为根视图
4、如果调用了[super loadView]; ,系统就优先去加载stroyboard或者xib的视图

loadView的实际应用

我们先看看一个实际开发中的问题,加载一个Xib控制器。

/// 视图加载完成
- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *clickBtn = [[UIButton alloc]initWithFrame: CGRectMake(100, 200,[UIScreen mainScreen].bounds.size.width - 200, 50)];
    [clickBtn setTitle:@"跳转到Xib控制器" forState:UIControlStateNormal];
    [self.view addSubview:clickBtn];
    
    [clickBtn addTarget:self action:@selector(clickBtnClick) forControlEvents:UIControlEventTouchUpInside];
    
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}

- (void)clickBtnClick{
    XibViewController *vc = [[XibViewController alloc]initWithNibName:@"XibViewController" bundle:nil];
//    [vc loadView];
    vc.beautifulImageView.image = [UIImage imageNamed:@"img2"];
    vc.titleLab.text = @"我想看美女";
    [self presentViewController:vc animated:YES completion:nil];
}
Xib视图控制器

运行后点击按钮跳转到Xib控制器,发现即使我在跳转之前重新设置了图片和文字,但是加载的还是默认的,那怎么办?
上边已经论证了,loadView有一个方法就是用来加载控制器的根视图的,修改之后出现默认的图片和文字是因为控制器push出来之后,根视图也会加载出来,但是系统默认会去Xib文件中寻找是否有可用的view,发现有一个默认的view,直接加载出来,即使你修改也没用。

解决办法:重写loadview的方法,让系统去使用我们自定义的视图view

- (void)clickBtnClick{
    XibViewController *vc = [[XibViewController alloc]initWithNibName:@"XibViewController" bundle:nil];
    [vc loadView];
    vc.beautifulImageView.image = [UIImage imageNamed:@"img2"];
    vc.titleLab.text = @"我想看美女";
    [self presentViewController:vc animated:YES completion:nil];
}

运行
loadview使用后

大功告成!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269