1. 控制器View的創(chuàng)建
首先我們來(lái)看一下控制器view創(chuàng)建的流程圖

從圖中我們可以看出,在控制器view加載過(guò)程中有兩個(gè)重要的方法loadView和viewDidLoad。下面我們來(lái)重點(diǎn)了解一下這兩個(gè)方法。
loadView方法
作用:loadView方法是用來(lái)負(fù)責(zé)創(chuàng)建UIViewController的view。首先判斷下有沒(méi)有指定storyboard或者xib,如果指定,就會(huì)加載它們描述的控制器的view,如果沒(méi)有指定,創(chuàng)建一個(gè)空的view。
什么時(shí)候調(diào)用:每次訪(fǎng)問(wèn)UIViewController的view,當(dāng)view為nil,就會(huì)調(diào)用loadView方法。
viewDidLoad
作用:一般我們會(huì)在這里做界面上的初始化操作,比如往view中添加一些子視圖等。
什么時(shí)候調(diào)用:每當(dāng)view創(chuàng)建完畢的時(shí)候,最終都會(huì)調(diào)用viewDidLoad方法。
其次,在view創(chuàng)建過(guò)程中還有一些需要注意的地方。
通過(guò)storyboard創(chuàng)建的控制器,或者通過(guò)xib創(chuàng)建的控制器的view,系統(tǒng)會(huì)幫我們加載控制器的view,具體內(nèi)部實(shí)現(xiàn)可以看iOS-UIWindow詳解,在此不在贅述
2.ViewController *vc = [[ViewController alloc]init];
底層也會(huì)調(diào)用-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil方法。
(1).判斷下有沒(méi)有指定nibName,如果指定了,就會(huì)去加載指定的xib
(2).如果沒(méi)有指定,就會(huì)判斷下有沒(méi)有跟控制器類(lèi)名同名的xib,有,就會(huì)去加載
(3).判斷下有沒(méi)有跟控制器類(lèi)名同名的xib,但是后綴不帶Controller的xib,如果有,就會(huì)去加載
(4).如果沒(méi)有任何xib描述控制器的view,就不會(huì)加載xib。會(huì)創(chuàng)建一個(gè)顏色為clearColor的view。
2. 控制器View的生命周期
控制器View的生命周期方法
loadView:? ? ? ? ? ? ? ? ? ? ? ? 加載view
viewDidLoad:? ? ? ? ? ? ? ? ? view加載完畢
viewWillAppear:? ? ? ? ? ? ? 控制器的view將要顯示
viewWillLayoutSubviews: 控制器的view將要布局子控件
viewDidLayoutSubviews: 控制器的view布局子控件完成
viewDidAppear:? ? ? ? ? ? ? ? 控制器的view完全顯示
viewWillDisappear:? ? ? ? 控制器的view即將消失的時(shí)候
viewDidDisappear:? ? ? ? 控制器的view完全消失的時(shí)候
view生命周期方法調(diào)用順序
viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear
3. 控制器View的延遲加載
控制器的view是延遲加載的:創(chuàng)建控制器并不一定會(huì)創(chuàng)建控制器的view,等用到時(shí)再加載
下面我們通過(guò)一個(gè)小的程序來(lái)驗(yàn)證一下
AppDelegate.m
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {// Override point for customization after application launch.self.window = [[UIWindowalloc] initWithFrame:[UIScreenmainScreen].bounds];// 創(chuàng)建控制器,并一定會(huì)創(chuàng)建控制器的viewViewController *vc = [[ViewController alloc] init];? ? ? ? vc.view.backgroundColor = [UIColorredColor];self.window.rootViewController = vc;? ? ? ? [self.window makeKeyAndVisible];returnYES;}```ViewController.m
import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
// 自定義控制器的view
(void)loadView
{
NSLog(@"%s",func);
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor = [UIColor greenColor];
self.view = view;
}
// 控制器的view加載完成的時(shí)候調(diào)用
(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor blueColor];
NSLog(@"%s",func);
}```
此時(shí)打印我們發(fā)現(xiàn)控制器的view顏色是紅色的,這是因?yàn)関iew的get方法底層中實(shí)現(xiàn)了loadView 和 viewDidLoad方法,loadView中將view設(shè)置為綠色,viewDidLoad方法中又將view設(shè)置成藍(lán)色,但是最后被vc.view.backgroundColor = [UIColor redColor];設(shè)置為紅色。
1.2 storyboard 間接實(shí)例化(initWithCoder)
當(dāng)你從 storyboard 初始化 ViewController 時(shí),iOS 會(huì)使用 initWithCoder,而不是 initWithNibName 來(lái)初始化這個(gè) ViewController,然后那個(gè) storyboard 會(huì)在自己內(nèi)部生成一個(gè) nib (storyboard 實(shí)例化 view / ViewController 時(shí),會(huì)把 nib 的信息放在 Coder 中,調(diào)用 initWithCoder)。