iOS之控制器View的加载

首先我们得知道,控制器view是通过懒加载的方式进行加载的,即用到的时候再加载。loadView有什么作用,它与viewDidLoad有何区别.
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

最后补充

1.控制器view的生命周期:viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear

2.内存警告传递过程:手机内存不足产生事件->通知应用程序->调用应用程序代理方法->把事件传递给窗口->窗口传给控制器->调用控制器的内存警告方法

3.xib描述控制器view时,其File‘s Owner为对应的控制器类名,当通过xib自定义view或cell时,File‘s Owner不能是其类名,但可以是控制器的类名,总的来说File‘s Owner只能是控制器

时间: 2024-10-12 16:45:54

iOS之控制器View的加载的相关文章

控制器View的加载过程

1.控制器内部的view是延迟加载 1> 用到时再加载2> 加载完毕后会调用控制器的viewDidLoad方法 2.创建控制器的方式 1> 直接通过代码创建OneViewController *one = [[OneViewController alloc] init]; 如果调用init方法创建控制器(TwoViewController),那么在加载控制器view的时候: a.优先查找 “TwoView.xib” b.其次再查找 同名 的xib 文件 “TwoViewControlle

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

在面试中,面试官可能会问这样的问题,loadView有什么作用,它与viewDidLoad有何区别 首先我们得知道,控制器view是通过懒加载的方式进行加载的,即用到的时候再加载. loadView方法 当我们用到控制器view时,就会调用控制器view的get方法,在get方法内部,首先判断view是否已经创建,如果已存在,则直接返回存在的view,如果不存在,则调用控制器的loadView方法,在控制器没有被销毁的情况下,loadView也可能会被执行多次 viewDidLoad方法 当控制

UIKit框架(6)控制器view的加载方式

本篇文章,总结控制器管理的view是如何创建而来的,以及Xcode对控制器view创建的隐含规则 创建方式 方式一:alloc+init方式,空白view 应当在控制器的viewDidLoad方法中添加要对view进行的各种操作 方式二:alloc+initWithNib方式,即view是由xib设计的 方式三:从UIStoryboard对象加载的,即view是由storyboard设计的 方式四:重写控制器的loadView方法,该方法内进行创建view 如: - (void)loadView

控制器view的加载顺序initWithNibName &gt;&gt;&gt; viewDidLoad &gt;&gt;&gt; viewWillAppear &gt;&gt;&gt; viewDidAppear

-(void)viewWillAppear:(BOOL)animated { self.navigationController.navigationBarHidden=NO;// 邓超界:放在willAppear,不能放在viewDidLoad(因为先执行viewDidLoad,再执行viewWillAppear.还有当控制器没有dealloc,viewDidLoad不会在执行了) } 执行顺序: initWithNibName >>> viewDidLoad >>>

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

1.如何创建一个控制器 控制器常见的创建方式有以下几种: (1)通过storyboard创建 (2)直接创建 MJViewController *mj = [[MJViewController alloc] init]; (3)指定xib文件来创建 MJViewController *mj = [[MJViewController alloc] initWithNibName: @"MJViewController" bundle:nil]; 注意,创建xid后还要设置xid中哪个vi

iOS开发UI篇—懒加载

iOS开发UI篇—懒加载 1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化 2.使用懒加载的好处: (1)不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 (2)每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 3.代码示例 1 // 2 // YYViewController.m 3

源码03-02-09-控制器View懒加载

// // AppDelegate.m // 09-控制器View懒加载 #import "AppDelegate.h" #import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictio

iOS开发UI基础—懒加载

iOS开发UI基础-懒加载 1.懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化 2.使用懒加载的好处: (1)不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 (2)每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 3.代码示例 1 // 2 // YYViewController.m

iOS网络编程(三) 异步加载及缓存图片----&gt;SDWebImage

@SDWebImage提供一个UIImageView的类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. @SDWebImage的导入1.https://github.com/rs/SDWebImage 下载SDWebImage开源包2.将类包拖入工程,再导入MapKit.framework.ImageIO.framework两个框架3.SDWebImage是支持ARC的,在MRC的工程中要注意,可参考MRC工程配置ARC4.注意:SDWebImag