您的位置:首页 > 产品设计 > UI/UE

关于iOS 中UIViewController的生命周期以及相关视图(View)的探讨

2016-07-16 15:28 495 查看
最近朋友在面试的时候,面试官问到了关于iOS中UIViewController的生命周期以及相关视图(View)的问题,朋友对于自己的观点还是挺有信心的,但是面试官提出了异议,朋友回来便和我们聊起了此事,自己感觉面试官的回答有些问题,特在此发表以下本人对以上问题的理解。

1 先看一下有关的方法,相信大家都在熟悉不过

//类的初始化方法
+ (void)initialize;
//对象初始化方法(代码创建)
- (instancetype)init;
//当用代码创建UIViewController的时候,[[UIViewController alloc] init],此时系统会调用此方法,查看有没有相应的xib文件,如果没有,则会创建相应的UIViewController
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
//当从xib加载视图控制器时会调用此方法,但是此时视图控制器上的相关控件还没有创建出来,为nil
-(void)awakeFromNib;
//从归档初始化(从storyBoard加载)会调用此方法
- (instancetype)initWithCoder:(NSCoder *)coder;
//加载视图
-(void)loadView;
//加载视图完毕
- (void)viewDidLoad;
//将要布局子视图
-(void)viewWillLayoutSubviews;
//已经布局子视图
-(void)viewDidLayoutSubviews;
//已经展示
-(void)viewDidAppear:(BOOL)animated;
//将要展示
-(void)viewWillAppear:(BOOL)animated;
//将要消失
-(void)viewWillDisappear:(BOOL)animated;
//已经消失
-(void)viewDidDisappear:(BOOL)animated;
//内存警告
- (void)didReceiveMemoryWarning;
//被释放
-(void)dealloc;
//已经废除
- (void)viewWillUnload
//已经废除
- (void)viewDidUnload


2 详细介绍loadView方法

调用loadView方法来生成UIViewController.view,如果loadView不能生成UIViewController.view,系统将会反复调用loadView及viewDidLoad方法, 并且最终调用[super loadView] 方法返回UIViewController.view

我们知道,当我们从StoryBoard中加载ViewController时,我们在Controller中拖拽的视图是可以被初始化的,这里面有一点需要我们注意,如果我们需要向controller中视图进行传值设置,通过以下方法得到的Controller中,视图还没有被初始化创建出来



我们可以在ViewController2的storyBoard中拉一个label,然后关联到头文件中,会发现我们得到controller时,里面的视图对象并没有进行创建:



可以想象,如果我们这时候需要对label进行一些属性设置,必然失败。

有人提出可以在创建后,手动调以下loadView方法,我们试一下手动调用loadView后,label是被创建了出来,但是暴漏了一个更严重的问题,系统不在调用ViewDidLoad方法,这是十分有风险的,因为我们大部分的初始化代码都会放在这个方法里,所以手动调用loadView是一种错误的方法,apple文档声明对于loadView方法,我们从来都不要手动直接调用,那么我们如何实现创建后对成员对象进行传值设置呢?

iOS9中增加了这样一个方法:



这个方法十分有用,调用这个方法,会将视图创建出来,并且不会忽略viewDidLoad的调用。

在iOS9中,UIViewController还增加了下面一个布尔值的属性,可以用来判断controller的view是否已经加载完成:



3 注意点

当程序收到内存不足的警告后, 程序内存中的所有的UIViewController都将会收到didReceiveMemoryWarning调用消息,我们要在这个方法里面做相应的处理 目的是将当前不显示的UIViewController中的view释放掉(不会调用UIViewController的dealloc方法), 所以当该UIViewController再次显示的时候又要生成一次, 此时它会调用loadView-> viewDidLoad ->viewWillAppear等, 这时最容易造成内存泄漏!

4 总结

@ initialize函数并不会每次创建对象都调用,只有在这个类第一次创建对象时才会调用,做一些类的准备工作,再次创建这个类的对象,initalize方法将不会被调用,对于这个类的子类,如果实现了initialize方法,在这个子类第一次创建对象时会调用自己的initalize方法,之后不会调用,如果没有实现,那么它的父类将替它再次调用一下自己的initialize方法,以后创建也都不会再调用。因此,如果我们有一些和这个相关的全局变量,可以在这里进行初始化。

@ init方法和initCoder方法相似,只是被调用的环境不一样,如果用代码进行初始化,会调用init,从nib文件或者归档进行初始化,会调用initCoder。

@ loadView方法是开始加载视图的起始方法,除非手动调用,否则在ViewController的生命周期中没特殊情况只会被调用一次。

@ viewDidLoad方法是我们最常用的方法的,类中成员对象和变量的初始化我们都会放在这个方法中,在类创建后,无论视图的展现或消失,这个方法也是只会在将要布局时调用一次。

@ viewWillAppare:视图将要展现时会调用。

@ viewWillLayoutSubviews:在viewWillAppare后调用,将要对子视图进行布局。

@ viewDidLayoutSubviews:已经布局完成子视图。

@ viewDidAppare:视图完成显示时调用。

@ viewWillDisappare:视图将要消失时调用。

@ viewDidDisappare:视图已经消失时调用。

@ dealloc:controller被释放时调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息