ViewController详解

一、生命周期

当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序
1、 alloc                              创建对象,分配空间
2、init (initWithNibName)  初始化对象,初始化数据
3、loadView          从nib载入视图 ,通常这一步不需要去干涉。除非你没有使用xib文件创建视图
4、viewDidLoad       载入完成,可以进行自定义数据以及动态创建其他控件
5、viewWillAppear                视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了
6、viewDidAppear       视图已在屏幕上渲染完成当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反
1、viewWillDisappear            视图将被从屏幕上移除之前执行
2、viewDidDisappear     视图已经被从屏幕上移除,用户看不到这个视图了
3、dealloc                            视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放

关于viewDidUnload :在发生内存警告的时候如果本视图不是当前屏幕上正在显示的视图的话,  viewDidUnload将会被执行,本视图的所有子视图将被销毁,以释放内存,此时开发者需要手动对viewLoad、viewDidLoad中创建 的对象释放内存。 因为当这个视图再次显示在屏幕上的时候,viewLoad、viewDidLoad 再次被调用,以便再次构造视图。

二、view的加载过程

文字说明在表述流程的时候总是很费力的,我又找到了如下的两张图

跟随如下文字理解viewController对view加载过程:

1 先判断子类是否重写了loadView,如果有直接调用。之后调viewDidLoad完成View的加载。

2 如果是外部通过调用initWithNibName:bundle指定nib文件名的话,ViewController记载此nib来创建View。

3 如果initWithNibName:bundle的name参数为nil,则ViewController会通过以下两个步骤找到与其关联的nib。

A 如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;

B 找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。

4  如果子类没有重写的loadView,则ViewController会从StroyBoards中找或者调用其默认的loadView,默认的loadView返回一个空白的UIView对象。

注意第一步,ViewController是判断子类是否重写了loadView,而不是判断调用子类的loadView之后 ViewController的View是否为空。就是说,如果子类重写了loadView的话,不管子类在loadView里面能否获取到 View,ViewController都会直接调viewDidLoad完成View的加载。

三、view卸载过程图

跟随以下文字理解卸载过程:

1 系统发出警告或者ViewController本身调用导致didReceiveMemoryWarning被调用

2 调用viewWillUnload之后释放View

3 调用viewDidUnload

四、模拟器的调用顺序

我构架了这样一个环境,在该环境中有两个viewController,姑且命名为A和B,tag分别为1和2,A控制程序启动的时候即加载的界面,在A中放一个按钮,按下后会通过segue来调用到界面B;B 中页放一个按钮,通过执行

[self dismissModalViewControllerAnimated:YES];

来返回界面A

然后检测所有的函数调用,依次如下

加载A的时候依次调用

1 initWithCoder

1 loadView //如果说你进行了重写,会在这里调用,这一步可以参考下文

1 viewDidLoad

1 viewWillAppear

1 viewWillLayoutSubviews

1 viewDidLayoutSubviews

1 viewDidAppear

切换至B的时候依次调用

2 initWithCoder             //先将2初始化

1 prepareForSegue       //调用1的准备过度的函数,所以在该函数中可以对界面B的一些相关属性进行赋值

2 loadView    //如果这里进行了重写

2 viewDidLoad              //2界面加载

1 viewWillDisappear

2 viewWillAppear

2 viewWillLayoutSubviews

2 viewDidLayoutSubviews

2 viewDidAppear

1 viewDidDisappear

从B切换回A的时候依次调用

2 viewWillDisappear

1 viewWillAppear

1 viewDidAppear

2 viewDidDisappear

2 dealloc

顺序总结下来加载依次为:加载 - 显示 - 布局

完成顺序依次为:完成布局 - 完成显示  - 完成加载

小注:-(void)loadView;函数如果重写,下面是一个可能的demo

-(void)loadView

{

CGRect applicationFrame = [[UIScreenmainScreen] applicationFrame];

UIView *contentView = [[UIViewalloc] initWithFrame:applicationFrame];

contentView.backgroundColor = [UIColordarkGrayColor];

self.view = contentView;

UILabel *lab = [[UILabelalloc]initWithFrame:CGRectMake(100, 100, 100, 100)];

lab.text = @"HelloWorld";

[self.viewaddSubview:lab];

}

loadView虽然返回值为空,但必须在函数体内对self.view进行赋值,否则会在建立该界面的时候收到如下的log信息:

Application windows are expected to have a root view controller at the end of application launch

具体执行顺序为:代码执行了initWithCoder之后直接调用了三次loadView函数,并且没有调用其它函数(包括viewDidLoad 、viewWillDisappear、viewWillLayoutSubviews)

疑问:

暂不清楚为什么会调用三次,我的猜测是:上述三个函数分别检测了一遍view是否存在,发现不存在,所以各自调用了一遍viewLoad,最后发现依然不存在,所以上述三个函数分别返回了失败,加载完成

但矛盾的地方是:为什么上述三个函数本身没有执行到?底层到底做了什么?

五、view和ViewController的创建阶段,关于什么时候应该干什么

1、init

Allocating critical data structures required by your view controller

不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。

2、loadView

Creating your view objects

只初始化view,一般用于创建比较关键的view如tableViewController的 tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super  loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用 super的loadView方法,但建议不要重载这个方法。

3、viewDidLoad

Allocating or loading data to be displayed in your view

这时候view已经有了,最适合创建一些附加的view和控件了。有一点需要注意的是,viewDidLoad会调用多次(viewcontroller可能多次载入view,参见图2)。

4、viewWillAppear 这个一般在view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。

5、viewDidAppear 一般用于显示后,在切换动画后,如果有需要的操作,可以在这里加入相关代码。

6、viewDidUnload

Releasing references to view objects

Releasing data that is not needed when your view is not displayed

这时候viewController的view已经是nil了。由于这一般发生在内存警告时,所以在这里你应该将那些不在显示的view释放了。比 如你在viewcontroller的view上加了一个label,而且这个label是viewcontroller的属性,那么你要把这个属性设置 成nil,以免占用不必要的内存,而这个label在viewDidLoad时会重新创建。

7、dealloc

Releasing critical data structures required by your view controller

六、几点备注:

1、按结构可以对iOS的所有ViewController分成两类:

1)、主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITableViewController,UIViewController。

2)、用于控制和显示其他ViewController的ViewController。这种ViewController一般都是一个 ViewController的容器。如UINavigationController,UITabbarController。它们都有一个属 性:viewControllers。其中UINavigationController表示一种Stack式结构,push一个 ViewController或pop一次,因此后一个ViewController一般会依赖前一个ViewController。而 UITabbarController表示一个Array结构,各个ViewController是并列的。

第一种ViewController会经常被继承,用来显示不同的数据给用户。而第二种很少被继承,除非你真的需要自定义它。

2、当view被添加其他view中之前时,会调用viewWillAppear,而之后会调用viewDidAppear。

当view从其他view中移出之前时,会调用viewWillDisAppear,而之后会调用viewDidDisappear。

当view不在使用,而且是disappeared,受到内存警告时,那么viewController会将view释放并将其指向nil。

3、由于Controller加载View时,会自动将一些View对象指向其对应的IBOutlet变量。

所以当view被卸载时我们必须在viewDidUnload将这些变量release掉,ViewController不会自动做这件事。

具体做法是将变量设置为空,(注意和dealloc中将变量release的区别)注意此时Controller的view属性是空的。

时间: 2024-08-10 23:27:08

ViewController详解的相关文章

Present ViewController详解

阅读:15112014-04-29 13:58 标签:弹出窗popwindowit 参考:http://www.cnblogs.com/linyawen/archive/2012/06/09/2542784.html一.主要用途 弹出模态ViewController(弹出控制器)是IOS变成中很有用的一个技术,UIKit提供的一些专门用于模态显示的ViewController,如UIImagePickerController等.弹出模态ViewController主要使用于一下这几种情形: 1.

ViewController 详解

一.页面跳转1.利用UINavigationController,调用pushViewController,进行跳转:这种采用压栈和出栈的方式,进行Controller的管理.调用popViewControllerAnimated方法可以返回. PickImageViewController *ickImageViewController = [[PickImageViewController alloc] init];     [self.navigationController pushVi

iOS学习-UIActionSheet详解

1 // 2 // ViewController.m 3 // UIActionSheet详解 4 // 5 // Created by 大欢 on 16/1/25. 6 // Copyright © 2016年 bjsxt. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController ()<UIActionSheetDelegate> 12 13 - (I

UINavigationController使用详解

有一阵子没有写随笔,感觉有点儿手生.一个多月以后终于又一次坐下来静下心写随笔,记录自己的学习笔记,也希望能够帮到大家. 废话少说回到正题,UINavigationController是IOS编程中比较常用的一种容器view controller,很多系统的控件(如UIImagePickerViewController)以及很多有名的APP中(如qq,系统相册等)都有 用到.说是使用详解,其实我只会介绍几个自认为比较重要或者容易放错的地方进行讲解,下面让我们挨个探探究竟: 首先上一张图(来自苹果官

iOS开发——UI篇OC篇&amp;UICollectionView详解+实例

UICollectionView详解+实例 实现步骤: 一.新建两个类 1.继承自UIScrollView的子类,比如HMWaterflowView * 瀑布流显示控件,用来显示所有的瀑布流数据 2.继承自UIView的子类,比如HMWaterflowViewCell * 代表着瀑布流数据中的一个单元(一个格子) 3.总结 HMWaterflowView和HMWaterflowViewCell的关系实际上类似于 UITableView和UITableViewCell的关系 二.设计HMWater

ios中创建可以拖动的view原理和实现详解

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIE

ios新特征 ARC详解

IOS ARC 分类: IOS ARC2013-01-17 09:16 2069人阅读 评论(0) 收藏 举报 目录(?)[+] 关闭工程的ARC(Automatic Reference Counting) 顺带附上ARC教程 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流和讨论.请不要将本文的部分或全部内容用于商用,谢谢合作. 欢迎转载本文,但是转载请注明本文出处:http://www.onevcat.com/2012/06/arc-hand-by

NSURLSession详解

导语 现在NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS7,所以也可以使用. NSURLConnection相对于NSURLSession,安全性低.NSURLConnection下载有峰值,比较麻烦处理. 尽管适配最低版本iOS7,也可以使用NSURLSession.AFN已经不支持NSURLConnection. NSURLSession:默认是挂起状态,如果要请求网络,需要开启. [NSURLSessio

iOS Core Animation详解(四)AutoLayout中的动画

原创blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:AutoLayout定义了View的位置,也就是说,在Auto Layout的工程里,如果不修改约束本身,在视图重新绘制的时候,还会回到最开始的位置.AutoLayout中的动画与视图的位置和大小有关. 先看看效果 实现过程 在Storyboard上拖拽一