前言

在面试中,面试官可能会问这样的问题,loadView有什么作用,它与viewDidLoad有何区别?

首先我们得知道,控制器view是通过懒加载的方式进行加载的,即用到的时候再加载。

loadView方法

当我们用到控制器view时,就会调用控制器view的get方法,在get方法内部,首先判断view是否已经创建,如果已存在,则直接返回存在的view,如果不存在,则调用控制器的loadView方法,在控制器没有被销毁的情况下,loadView也可能会被执行多次

viewDidLoad方法

当控制器的loadView方法执行完毕,view被创建成功后,就会执行viewDidLoad方法,该方法与loadView方法一样,也有可能被执行多次。在开发中,我们可能从未遇到过执行多次的情况,那什么时候会执行多次呢?

比如A控制器push出B控制器,此时,窗口显示的是B控制器的view,此时如果收到内存警告,我们一般会将A控制器中没用的变量及view销毁掉,之后当我们从B控制器pop到A控制器时,就会再次执行A控制器的loadView方法与viewDidLoad方法。

如下图所示,注意控制台打印

控制器view的加载

先看一下Demo的文件结构,ViewController为A控制器,TestViewController为B控制器。

 

1.通过storyboard加载

当控制器通过storyboard加载时,需要指定storyboard的名称,控制器view最终就是storyboard所描述的样子,这个比较简单,不做详细阐述。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"TestViewController" bundle:nil];

TestViewController *testVC = [storyboard instantiateInitialViewController];

[self.navigationController pushViewController:testVC animated:YES];

}

2.通过xib加载

当控制器view通过xib加载的时候,可能会出现三种情况

a. 指定xib名称(OtherViewController.xib)

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

TestViewController *testVC = [[TestViewController alloc] initWithNibName:@"OtherViewController" bundle:nil];

[self.navigationController pushViewController:testVC animated:YES];

}

当我们指定了xib的名称,loadView方法就会去加载对应的xib(OtherViewController.xib),最终是这个样子的。

b.不指定xib名称1

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

TestViewController *testVC = [[TestViewController alloc] init];

[self.navigationController pushViewController:testVC animated:YES];

}

如果我们不指定xib名称,loadView就会加载与控制器同名的xib(TestViewController.xib),最终是这个样子的。

c.不指定xib名称2

我们先将TestViewController.xib这个文件删除掉,这个时候,我们再来运行程序,结果是这样的。

根据上图我们可以得知,当没有指定xib名称,且没有与控制器同名的xib时,会加载前缀与控制器名相同而不带controller的xib(TestView.xib)。

3.不通过sb\xib加载

将TestView.xib这个文件也删除掉,再来运行程序,结果是这样的

这么黑,难道没有创建控制器view?

如上图,控制器view是存在的,只不过颜色为clearColor,所以看到的黑色其实是UIWindow的。

4.重写loadView方法

我们重写TestViewController的loadView方法,里面不做任何事

- (void)loadView {

}

运行程序看结果

结果跟上面一样黑,不同的是,这次并没有创建view,注意看上图最外层并不是UIView。

如果我们希望控制器view加载出来的时候不是UIView而是其他控件,比如UIImageView,那我们就可以重写loadView。

- (void)loadView{

self.view = [[UIImageView alloc] init];

}

 

结论

1.重写loadView方法,则会根据重写的loadView方法创建view

2.控制器通过storyboard加载,则根据storyboard的描述创建view

3.控制器view通过xib加载,则根据nibName对应的xib创建view

4.没有指定nibName,则根据与控制器同名的xib创建view

5.没有同名的xib,则根据与控制器名前缀相同不带controller的xib创建view

6.如果都没有,则创建一个空白的xib

小细节

在上面的2、3两点结论中,不知道大家有没有一个疑问

为什么上面是说的控制器,而下面却说的控制器view?

笔者结合控制器的awakeFromNib方法给大家说明一下这个问题。

顾名思义,当控制器从nib加载的时候就会调用这个方法

先来看看通过storyboard加载的情况

//A控制器中代码

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"TestViewController" bundle:nil];

TestViewController *testVC = [storyboard instantiateInitialViewController];

[self.navigationController pushViewController:testVC animated:YES];

}

//B控制器中代码

- (void)awakeFromNib {

NSLog(@"B通过nib加载");

}

控制台打印了“B通过nib加载”,即调用了B控制器的awakeFromNib方法。

将之前删除的TestViewController.xib文件重写添加进去,再来看通过xib加载的情况。

//A控制器中代码改为如下

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

TestViewController *testVC =[[TestViewController alloc] init];

[self.navigationController pushViewController:testVC animated:YES];

}

//B控制器中代码不变

控制台没有任何输出,即B控制器的awakeFromNib方法并没有被调用。

结论

storyboard加载的是控制器及控制器view,而xib加载的仅仅只是控制器的view。

 

iOS之深入了解控制器View的加载相关推荐

  1. iOS开发之控制器创建与加载(生命周期)

    1.如何创建一个控制器 控制器常见的创建方式有以下几种: (1)通过storyboard创建 (2)直接创建 MJViewController *mj = [[MJViewController all ...

  2. iOS控制器与视图加载方法

    转载记录, 请看原文: 1. iOS中的各种加载方法(initWithNibName,loadNibNamed,initWithCoder,awakeFromNib等等)简单使用   http://w ...

  3. Android View的加载过程

    2019独角兽企业重金招聘Python工程师标准>>> 大家都知道Android中加载view是从Activity的onCreate方法调用setContentView开始的,那么V ...

  4. IOS开发之下拉刷新和上拉加载更多

    IOS开发之下拉刷新和上拉加载更多 1.简介 常用的下拉刷新和上拉加载更多的实现方式 (1)UIRefreshControl (2)EGOTableViewRefresh (3)AH3DPullRef ...

  5. iOS开发:利用SDWebImage实现图片加载与缓存

    iOS开发:利用SDWebImage实现图片加载与缓存 SDWebImage是一套开源框架,这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL ...

  6. iOS 开发之 pdf 文档的加载与浏览的 4 种方式

    原文链接:http://www.jianshu.com/p/1d4305a02ea5 在我们的开发中,有些像电子书类型的 app 的开发会涉及到 pdf 文档的加载与展示.由于笔者项目中正好涉及到这块 ...

  7. IOS Swift5 WkWebView 跳转网页后 加载页面结果方法拦截(WKNavigationResponse)

    步骤 找到拦截的方法 参数说明 获取状态码,判断状态 先说明一下我的需求,这里是用wkwebview嵌套了一层h5的页面,在 h5页面做跳转时,会有可能地址加载404的情况,这个时候会显示白屏,然后我 ...

  8. SpringMVC几个核心类(控制器核心类,加载配置文件核心类,处理url影射核心类,处理视图资源核心类,方法动态调用核心类)

    核心类 制器核心类: •org.springframework.web.servlet.DispatcherServlet  - 配置web.xml   加载配置文件核心类: •org.springf ...

  9. iOS UITableView下拉刷新上拉加载更多EGOTableViewPullRefresh类库使用初级剑侠篇(欢迎提建议和分享遇到的问题)

    这篇文章说下:MJRefresh和  EGOTableViewPullRefresh 的使用方法最下面有原理说明,若有不对或者建议请评论指出,先谢谢了: 首先是英文原文和类库下载地址:https:// ...

最新文章

  1. Convolutional-MLPs改造
  2. tensorflow 卷积、反卷积形式的去噪自编码器
  3. 内核 kmap_atomic分析
  4. linux下的crontab
  5. 计算机采购类增值税税率是多少,各个行业的税率是多少?
  6. java object数组转实体类_详解Java中String JSONObject JSONArray List实体类转换
  7. 7-157 求一元二次方程的根 (20 分)
  8. Visual Studio 常用快捷键(一)
  9. php str_replace技巧-避免重复替换
  10. python3.6.5 安装第三方库
  11. python错误:ImportError: DLL load failed: 找不到指定的程序,from PyQt6 import QtCore, QtGui, QtWidgets
  12. Ubuntu安装Mysql5.7
  13. 我的 2020 总结:Never Settle
  14. 2016 360校招笔试编程题
  15. 私有云盘的搭建(owncloud、seafile)
  16. TPshop登录接口测试
  17. Android Espresso(一)——环境建立
  18. 第十二章:email-mailbox:管理email归档-imaplib:IMAP4客户库-邮箱状态
  19. matlab构造传递函数
  20. 网络流之最大流算法——EK算法(通俗讲解)

热门文章

  1. 构建商品评价的分类器
  2. ps -ef |grep 输出的具体含义
  3. Centos Git1.7.1升级到Git2.2.1
  4. 5G空口存疑 革新还是4G演进?
  5. 洛谷P2904 [USACO08MAR]跨河River Crossing 动态规划
  6. 怎么一个好的短信验证码接口接入到自己的企业网站和APP程序当中选择
  7. 在项目中迁移MS SQLServer到Mysql数据库,实现MySQL数据库的快速整合
  8. 双核处理(动态规划)
  9. MAC安装Win10出现”在efi系统上,windows只能安装到gpt分区”问题的解决
  10. Android实践 -- 监听应用程序的安装、卸载