iOS之深入了解控制器View的加载

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看108 回复回复3 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 108|回复: 3
收起左侧

iOS之深入了解控制器View的加载

[复制链接]
cocoaswift 发表于 2016-7-26 11:13:46 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑



1、前言

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

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




2、loadView方法

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




3、viewDidLoad方法

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


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

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

iOS之深入了解控制器View的加载 1

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 1





4、控制器view的加载

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

iOS之深入了解控制器View的加载 2

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 2




4.1、通过storyboard加载

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

[Objective-C] 纯文本查看 复制代码
- (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];
}




4.2、通过xib加载

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


4.2.1、指定xib名称(OtherViewController.xib)

[Objective-C] 纯文本查看 复制代码
- (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),最终是这个样子的

iOS之深入了解控制器View的加载 3

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 3



4.2.2、不指定xib名称1

[Objective-C] 纯文本查看 复制代码
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  TestViewController *testVC = [[TestViewController alloc] init];
  [self.navigationController pushViewController:testVC animated:YES];
}


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

iOS之深入了解控制器View的加载 4

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 4



4.2.3、不指定xib名称2

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

iOS之深入了解控制器View的加载 5

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 5


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



4.3、不通过sb\xib加载

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

iOS之深入了解控制器View的加载 6

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 6


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

iOS之深入了解控制器View的加载 7

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 7


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



4.4、重写loadView方法

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

[Objective-C] 纯文本查看 复制代码
- (void)loadView {
}


运行程序看结果

iOS之深入了解控制器View的加载 8

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 8


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

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

[Objective-C] 纯文本查看 复制代码
- (void)loadView{
  self.view = [[UIImageView alloc] init];
}


iOS之深入了解控制器View的加载 9

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 9





5、结论

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




6、小细节

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

iOS之深入了解控制器View的加载 10

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 10


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

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

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


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

[Objective-C] 纯文本查看 复制代码
//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加载");
}


iOS之深入了解控制器View的加载 11

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 11


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

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

[Objective-C] 纯文本查看 复制代码
//A控制器中代码改为如下
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  TestViewController *testVC =[[TestViewController alloc] init];
  [self.navigationController pushViewController:testVC animated:YES];
}
//B控制器中代码不变


iOS之深入了解控制器View的加载 12

iOS之深入了解控制器View的加载 - 敏捷大拇指 - iOS之深入了解控制器View的加载 12


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



6.1、结论

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




作者:codingZero

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 2金钱 +10 贡献 +10 专家分 +11 收起 理由
Mustang + 1 观点不错哈,顶!
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

蚊香酱 发表于 2016-7-26 14:46:01 | 显示全部楼层
这个讲解的不错
安卓大师 发表于 2016-7-26 19:11:07 | 显示全部楼层

同赞
我是90后 发表于 2016-7-27 05:13:34 | 显示全部楼层
透彻!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表