前言
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIViewController : UIResponder <NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment>
@available(iOS 2.0, *) public class UIViewController : UIResponder, NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment
1、ViewController 的创建
-
Objective-C
// 实例化视图控制器
UiViewController *viewController = [[UiViewController alloc] init];
// 设置 window 的根视图控制器
self.window.rootViewController = viewController;
-
Swift
// 实例化视图控制器
let viewController:UiViewController = UiViewController()
// 设置 window 的根视图控制器
self.window?.rootViewController = viewController
2、ViewController 的设置
-
Objective-C
// 设置 viewController 的背景颜色
self.view.backgroundColor = [UIColor redColor];
// 向 viewController 上添加视图
[self.view addSubview:button];
// 向 viewController 上添加视图控制器
[self addChildViewController: viewController2];
[self.view addSubview:viewController2.view];
-
Swift
// 设置 viewController 的背景颜色
self.view.backgroundColor = UIColor.redColor()
// 向 viewController 上添加视图
self.view.addSubview(button)
// 向 viewController 上添加视图控制器
self.addChildViewController(viewController2)
self.view.addSubview(viewController2.view)
3、ViewController 的界面跳转
-
Objective-C
// 跳转到 指定 页面
[self presentViewController:viewController1 animated:YES completion:nil];
// 返回到 上一个 页面
[self dismissViewControllerAnimated:YES completion:nil];
-
Swift
// 跳转到 指定 页面
self.presentViewController(viewController1, animated: true, completion: nil)
// 返回到 上一个 页面
self.dismissViewControllerAnimated(true, completion: nil)
4、ViewController 的生命周期
![viewcontroller1]()
-
相关方法执行顺序:
init -> loadView -> viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear -> viewWillUnload -> viewDidUnload —> dealloc
分配内存 -> 加载视图 -> 视图已经加载 -> 视图将要出现 -> 将要布局子视图 -> 已经布局子视图 -> 视图已经出现 -> 视图将要消失 -> 视图已经消失 -> 将要销毁视图 (iOS 6+ 已废弃)-> 已经销毁视图(iOS 6+ 已废弃) -> 释放内存
-
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 会从 StroyBoard 中找或者调用其默认的 loadView,默认的 loadView 返回一个空白的 UIView 对象。
-
loadView
- (void)loadView;
public func loadView()
- 加载视图层次结构,用纯代码开发应用程序时使用,功能和 Storyboard & XIB 是等价的,如果重写了 loadView,Storyboard & XIB 都无效。如果控制器的 view 为 nil,会自动调用 loadView 方法,创建视图。
-
awakeFromNib
- (void)awakeFromNib;
public func awakeFromNib()
- 从 Stroyboard 加载,还没有被设置 frame & bounds。这个方法用的时候,outlet 还没有连接起来,是 ViewController 刚从 storyboard 建的时候没有完全建好,不过可能有一些事情要在这个方法里面完。
-
viewDidLoad
- (void)viewDidLoad;
public func viewDidLoad()
用这个的时候,ViewController 已经完全好了,outlet 也已经连接好了。但是还没有在屏幕上显示出来。这个方法里面可以放很多设置的代码。这个方法执行的时候,view 的 bounds 还没有。先 load,再 appear。
视图加载完成后执行,可以做一些数据初始化的工作,如果用纯代码开发,不要在此方法中设置界面 UI。如果是 Storyboard 开发,可以动态添加一些控件,以及加载数据。
-
viewWillAppear
- (void)viewWillAppear:(BOOL)animated;
public func viewWillAppear(animated: Bool)
这个方法调用的时候,视图的 bounds 已经有了。
视图只会 loaded 一次,但是会 appear 或者 disappear 很多次。不变的东西,放在 viewDidLoad 里面。和几何相关的,放在 viewWillAppear 里面。这点对项目的优化很重要。就好似顶层的 view,旋转 ipad 什么的都需要改变顶层的 view 的大小,当一个 ViewController 的生命周期到这里的时候,就可以在这里的最后时刻来调整 view 的排列或者几何特性。
这里也设置做一些 lazy execution for performance。比如:需要按一个 button,出现一个 view 什么的。这里设置,开销很大。耗时很长的事情最好在 viewWillAppear 里另开一个线程运行,然后在 view 里面放一个小小的 spinning wheel。
-
viewWillLayoutSubviews
- (void)viewWillLayoutSubviews;
public func viewWillLayoutSubviews()
-
viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated;
public func viewWillDisappear(animated: Bool)
- 这个方法在视图将要消失的时候调用。要消失的时候,如果要记得现在的运行情况,如可以记的 scroll 的 position。但是,不要在这个方法里面写太多的东西,否则 App 会崩溃的。另外开线程来处理任何 UI 的改变,或者如果是不怎么废资源的话就直接写入硬盘。
-
Objective-C
// 纯代码加载视图
- (void)loadView {
[super loadView];
}
// 从 Nib 加载视图
- (void)awakeFromNib {
[super awakeFromNib];
}
// 视图已经加载
- (void)viewDidLoad {
[super viewDidLoad];
}
// 视图将要出现,在 viewDidLoad 执行完成之后执行
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
// 将要布局子视图
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
}
// 已经布局子视图
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
}
// 视图已经出现
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
// 视图将要消失
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
// 视图已经消失,不是销毁
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
-
Swift
// 纯代码加载视图
override func loadView() {
super.loadView()
}
// 从 Nib 加载视图
override func awakeFromNib() {
super.awakeFromNib()
}
// 视图已经加载
override func viewDidLoad() {
super.viewDidLoad()
}
// 视图将要出现,在 viewDidLoad 执行完成之后执行
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
// 将要布局子视图
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
}
// 已经布局子视图
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
// 视图已经出现
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
// 视图将要消失
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
}
// 视图已经消失,不是销毁
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
}
5、ViewController 更新布局约束
通过代码为 xib 或 storyboard 中 view 增加约束时,尽量避免在 viewDidLoad 中执行,最好放在 updateViewConstraints(UIViewController 中) 或者 updateConstraints(UIView 中)中,记得调用 [super updateViewConstraints] 或者 [super updateConstraints];
如果你真的写在 viewDidLoad 里了,那么可能会遇到这种崩溃错误 Terminating app due to uncaught exception "NSInternalInconsistencyException"。
代码设置约束时,需设置该 view 的 translatesAutoresizingMaskIntoConstraints 属性已设置为 NO。
-
Objective-C
// 更新视图控制器中视图的布局约束
- (void)updateViewConstraints {
// 在这里为你的 view 添加约束
[super updateViewConstraints];
}
// 更新视图布局约束
- (void)updateConstraints {
// 在这里为你的 view 添加约束
[super updateConstraints];
}
-
Swift
// 更新视图控制器中视图的布局约束
override func updateViewConstraints() {
// 在这里为你的 view 添加约束
super.updateViewConstraints()
}
// 更新视图布局约束
override func updateConstraints() {
// 在这里为你的 view 添加约束
super. updateConstraints()
}
6、ViewController 的内存警告