一、UIViewController 的生命周期

下面带 (NSObject)的方法是NSObject提供的方法。其他的都是UIViewController 提供的方法。

load   (NSObject)

initialize   (NSObject)

init   (NSObject)

initWithCoder

initWithNibName

awakeFromNib   (NSObject)

loadView

viewDidLoad

viewWillAppear

updateViewConstraints

viewWillLayoutSubviews

viewDidLayoutSubviews

viewDidAppear

viewWillDisappear

viewDidDisappear

dealloc    (NSObject)

didReceiveMemoryWarning

二、load、initialize、init

load、initialize是继承的NSObject的方法。这些在其他文章里写过,就不详述了。大体说下。

在main方法还没执行的时候 就会 加载所有类,调用所有类的load方法。

一般会在load中实现Method Swizzle。

初始化对象,调用alloc的时候会调用initialize方法。这个时候是分配内存。

init方法是在内存中创建好对象。

三、 initWithCoder、initWithNibName、awakeFromNib

1、initWithCoder、awakeFromNib

initWithCoder:反归档,如果对象是从文件解析来的 就会调用。

awakeFromNib: 从xib或者storyboard加载完毕 会调用。
新建UIView的子类并且想在load nib的时候做一些初始化工作的时候 可以重写awakeFromNib。bundle在load nib后会给每个view对象发送一个awakeFromNib消息。

2、用storyboard,顺序:

initialize -> initWithCoder -> awakeFromNib -> loadView

2、用Xib或者纯代码:

如果用[[VC alloc] init] 来初始化:

initialize -> init -> initWithNibName -> loadView

如果用[[VC alloc] initWithNibName:@“VC” bundle:nil] 来初始化:

initialize -> initWithNibName -> loadView

使用Xib来实现VC的时候,不要重写loadView方法。如果重写了loadView方法,则Xib中View就会消失,变成空View。

四、loadView

1、要重新设置View的时候,在loadView中去创建UIViewController的view,也就是self.view。

在这个方法中主要完成一些关键view的初始化工作。加载成功后接着调用viewDidLoad方法。

在loadView之前,self.view是不存在的,也就是说view还没有被初始化,loadView完成后view就建立好了。

比如:

- (void)loadView {
NSLog(@"loadView中调用self.view : %@", self.view);
}

这样会直接崩溃,因为self.view 还没创建。

在重写的loadView中调用[super loadView],会自动初始化self.view。如下方式就不会崩溃:

- (void)loadView {
[super loadView];
NSLog(@"loadView中调用self.view : %@", self.view);
}

2、每次访问UIViewController的view(比如vc.view、self.view)而且view为nil,loadView方法就会被调用。

- (void)loadView {
[super loadView];
NSLog(@"loadView中调用self.view : %@", self.view);
} - (void)viewDidLoad {
[super viewDidLoad];
self.view = nil;
self.view.backgroundColor = [UIColor redColor]; //这时候view为nil,会再次调用loadView方法。执行完loadView后继续执行viewDidLoad方法,这样就死循环了。
}

上面代码 直接就死循环了,一直执行loadView和viewDidLoad方法。

3、loadView中自定义了view,那么xib、storyboard中设置的页面就会失效,frame也是无效的。如:

- (void)loadView {
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
customView.backgroundColor = [UIColor redColor];
self.view = customView;
}

上面代码执行的效果是 全屏都是红色。

4、修改self.view的大小,可以在 viewDidLayoutSubviews 方法里去修改:

- (void)viewWillLayoutSubviews {
    self.view.frame = CGRectMake(, , , );
}

5、默认的[super loadView] 中做了哪些事情:

5.1、如果UIViewController制定xib的名字或者storyboard 进行初始化 ,这样就会根据传入的xib的名字 去初始化view。如下代码:

XXViewController *xxVC = [[XXViewController alloc] initWithNibName:@"XXController" bundle:nil];

或者:

UIStoryboard *sb = [UIStoryboard storyboardWithName: @"XXSB" bundle: nil];
XXViewController *vc =[sb instantiateViewControllerWithIdentifier: @"XxxxViewController"];

5.2、如果xib没有显示的指定名称,就默认加载和UIViewController同名的xib文件。

5.3、如果没有找到xib文件就会创建 一个空白的UIView,这个view的frame为屏幕的大小。

五、viewDidLoad

loadView执行完成后调用viewDidLoad,viewDidLoad中主要完成界面的初始化 。如:往view上添加子视图、读取数据等。

页面打开后,如果没有销毁 就只执行一次。

六、viewWillAppear

viewDidLoad执行完成后就执行viewWillAppear。每次打开页面都会执行viewWillAppear。比如:从A页面push到B页面,然后从B页面返回到A页面的时候,viewDidLoad就不再执行,而viewWillAppear还是会执行。

如果要求每次显示该页面的时候都要刷新网络数据,就可以在viewWillAppear做网络请求的操作。

七、updateViewConstraints

主要功能是更新view的约束,并会调用其所有子视图的该方法去更新约束。

ViewController的View在更新视图布局时,会先调用ViewController的updateViewConstraints 方法。我们可以通过重写这个方法去更新当前View的内部布局,而不用再继承这个View去重写-updateConstraints方法。

两个方法都需要在方法实现的最后调用父类的该方法。并且这两个方法不建议直接调用。

- (void)updateViewConstraints {
//在这里给view添加约束,请确保该view的translatesAutoresizingMaskIntoConstraints属性已设置为false
[super updateViewConstraints];
}

如果是纯代码 用 frame布局,这个方法不会被调用。如果是 xib、storyboard 用 frame 布局也不会被调用,只有在使用Autolayout布局的时候才会被调用。

尽量将第一次初始化约束 写到init、viewDidLoad 这种方法中。

updateConstraints并不应该用来给视图添加初始的约束,它更适合用于周期性地更新视图的约束,或者在添加约束过于消耗性能的情况下将约束写到该方法中。

当我们在响应事件时(例如点击按钮时)对约束的修改如果写到updateConstraints中,会让代码的可读性非常差,同时会让性能比写到updateConstraints 还差。

这些在后面写约束的时候再详细讨论。

八、viewWillLayoutSubviews

view即将布局其Subviews。比如view的bounds改变了,要调整Subviews的位置,在调整之前要做的一些工作就可以在该方法中实现。

我们可以在这里设置 subviews 的 frame 属性。

在 Autolayout 机制被调用之前,viewWillLayoutSubviews 会被调用,在 Autolayout 机制被调用之后,viewDidLayoutSubviews 会被调用。即在 viewWillLayoutSubviews 和 viewDidLayoutSubviews 之间,Autolayout 机制会被调用。所以从viewWillLayoutSubviews 中获取的frame 是老的frame,从viewDidLayoutSubviews获取的frame才是正确的frame。

比如xib中设置了约束,然后 在viewDidLoad中设置frame,真实的位置还是根据xib中的约束显示的。

而且在viewWillLayoutSubviews中修改frame也是不生效的,那么,如何才能用代码修改布局生效?

方法一:
在viewDidLayoutSubviews中修改frame,这是最简单的方法。

方法二:推荐做法

在updateConstraints中修改约束。
方法三:
在viewWillLayoutSubviews中修改约束

九、viewDidLayoutSubviews

控制器的view布局子控件完成。这里获取的frame才是最正确的frame。

如果控件用的约束来布局的,在viewDidLayoutSubviews 中 去设置视图的frame 是无效的。

如果控件是用frame来布局的,在viewDidLayoutSubviews 中 去设置视图的frame 是有效的。

self.view 在viewDidLayoutSubviews 中 去设置 frame 是有效的。

十、viewWillDisappear

控制器的view即将消失的时候

十一、viewDidDisappear

控制器的view完全消失的时候

十二、 dealloc

当对象被释放的时候调用dealloc。

ARC中dealloc方法中常用的一些作用:

在dealloc中移除掉notification,解除delegate关系。

看一个类中是否有循环引用,可以用Instrument或者FBMemoryProfiler,不过最简单的还是在dealloc里打印日志。

十三、didReceiveMemoryWarning

当系统内存不足时,VC的didReceiveMemoryWarining 方法会被调用,VC所在的导航栈(self.navigationController.viewControllers)中的VC 也会被调didReceiveMemoryWarining。

didReceiveMemoryWarining 会判断当前VC的view是否显示在window上,

如果没有显示在window上,则didReceiveMemoryWarining 会自动将VC 的view以及其所有子view全部销毁。

如果当前UIViewController的view显示在window上,则不销毁该viewcontroller的view。

AppStore中一些可以释放内存的APP,就是先不断增加使用的内存,然后系统检测到内存不足的时候 会自动进行回收。

文章对应的代码地址:GitHub地址

UIViewController生命周期-完整版的更多相关文章

  1. monobehaviour生命周期完整版

  2. 你真的了解UIViewController生命周期吗?

    一:首先了解一下生命周期图 二:UIViewController 生命周期介绍 1.通过alloc init 分配内存,初始化controller. 2.loadView loadView方法默认实现 ...

  3. initWithFrame、initWithCoder、awakeFromNib的区别和调用次序 & UIViewController生命周期 查缺补漏

    当我们创建或者自定义一个UI控件时,就很可能会调用awakeFromNib.initWithCoder .initWithFrame这些方法.三者的具体区别如下: initWithFrame: 通过代 ...

  4. UIViewController生命周期

    UIViewController生命周期

  5. iOS对UIViewController生命周期和属性方法的解析

    目录[-] iOS对UIViewController生命周期和属性方法的解析 一.引言 二.UIViewController的生命周期 三.从storyBoard加载UIViewController实 ...

  6. 【iOS开发】iOS对UIViewController生命周期和属性方法的解析

    iOS对UIViewController生命周期和属性方法的解析 一.引言 作为MVC设计模式中的C,Controller一直扮演着项目开发中最重要的角色,它是视图和数据的桥梁,通过它的管理,将数据有 ...

  7. UIViewController生命周期控制

    UIViewController生命周期控制 UIViewController介绍 官方的介绍例如以下 The UIViewController class provides the fundamen ...

  8. 【iOS】UIViewController生命周期

    UIViewController有2周期: 在UIViewController中,View存在两个循环:载入循环和卸载循环. 载入循环 1>程序请求controller的view. 2>假 ...

  9. UIViewController生命周期控制-开发规范

    从网上各位iOS们收集并总结: 各方法使用: init 中初始化一些UI组件,比如UIButton,UILabel等 loadView 中 createFields 接受参数,初始化变量 create ...

随机推荐

  1. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  2. Git Bash的一些命令和配置

    查看git版本号: git --version 如果是第一次使用Git,你需要设置署名和邮箱: $ git config --global user.name "用户名" $ gi ...

  3. SQL Server常见数据类型介绍

    数据表是由多个列组成,创建表时必须明确每个列的数据类型,以下列举SQL Server常见数据类型的使用规则,方便查阅. 1.整数类型 int 存储范围是-2,147,483,648到2,147,483 ...

  4. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  5. html5 canvas常用api总结(二)--绘图API

    canvas可以绘制出很多奇妙的样式和美丽的效果,通过几个简单的api就可以在画布上呈现出千变万化的效果,还可以制作网页游戏,接下来就总结一下和绘图有关的API. 绘画的时候canvas相当于画布,而 ...

  6. [原]Redis主从复制各种环境下测试

    Redis 主从复制各种环境下测试 测试环境: Linux ubuntu 3.11.0-12-generic 2GB Mem 1 core of Intel(R) Core(TM) i5-3470 C ...

  7. [BootStrap] 富编辑器,基于wysihtml5

    在我的周围,已经有很多人在使用BootStrap,但对于任何一个带留言.评论.提问.文章编辑功的网站,编辑器永远是重中之重,显然,早期的编辑器完全没考虑过BootStrap的出现,或皮肤跟网站不匹配, ...

  8. openresty 前端开发入门四之Redis篇

    这章主要演示怎么通过lua连接redis,并根据用户输入的key从redis获取value,并返回给用户 操作redis主要用到了lua-resty-redis库,代码可以在github上找得到 而且 ...

  9. C# Entity Framework并发处理

    原网站:C# Entity Framework并发处理 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制.从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NE ...

  10. 【腾讯Bugly干货分享】WebVR如此近-three.js的WebVR示例解析

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff1689a6c9121b1adb16 作者:苏晏烨 关于WebVR 最 ...