前言
一直忽略的視圖控制器的生命周期問題,當(dāng)被面試官追問時(shí),發(fā)現(xiàn)自己知之甚淺,特此,總結(jié)下來(lái)。
視圖控制器創(chuàng)建方式
方式一(init加載):
CodeViewController *VC = [[CodeViewController alloc]init];
方式二(xib加載):
XibViewController *VC = [[XibViewController alloc]initWithNibName:@"XibViewController" bundle:[NSBundle mainBundle]];
方式三(Storyboard加載):
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"StoryBoardVC" bundle:[NSBundle mainBundle]];
StbViewController *VC = [sb instantiateViewControllerWithIdentifier:@"StoryBoardViewController"];
方式四(NSCoding協(xié)議加載):
NSCoderViewController *VC = [[NSCoderViewController alloc]initWithCoder:nil];
[self presentViewController:VC animated:YES completion:nil];
方式一輸出:
2019-01-18 17:27:08.801819+0800 LifeCyleVC[6591:1028822] +[CodeViewController initialize]
2019-01-18 17:27:08.802087+0800 LifeCyleVC[6591:1028822] -[CodeViewController initWithNibName:bundle:]
2019-01-18 17:27:08.802268+0800 LifeCyleVC[6591:1028822] -[CodeViewController init]
2019-01-18 17:27:08.802917+0800 LifeCyleVC[6591:1028822] -[CodeViewController loadView]
2019-01-18 17:27:08.803134+0800 LifeCyleVC[6591:1028822] -[CodeViewController viewDidLoad]
2019-01-18 17:27:08.804736+0800 LifeCyleVC[6591:1028822] -[CodeViewController viewWillAppear:]
2019-01-18 17:27:08.806116+0800 LifeCyleVC[6591:1028822] -[CodeViewController viewWillLayoutSubviews]
2019-01-18 17:27:08.806240+0800 LifeCyleVC[6591:1028822] -[CodeViewController viewDidLayoutSubviews]
2019-01-18 17:27:09.307427+0800 LifeCyleVC[6591:1028822] -[CodeViewController viewDidAppear:]
方式二輸出:
2019-01-18 16:32:07.414444+0800 LifeCyleVC[5502:834637] +[XibViewController initialize]
2019-01-18 16:32:07.414708+0800 LifeCyleVC[5502:834637] -[XibViewController initWithNibName:bundle:]
2019-01-18 16:32:07.416775+0800 LifeCyleVC[5502:834637] -[XibViewController loadView]
2019-01-18 16:32:07.416925+0800 LifeCyleVC[5502:834637] -[XibViewController viewDidLoad]
2019-01-18 16:32:07.418489+0800 LifeCyleVC[5502:834637] -[XibViewController viewWillAppear:]
2019-01-18 16:32:07.420077+0800 LifeCyleVC[5502:834637] -[XibViewController viewWillLayoutSubviews]
2019-01-18 16:32:07.420202+0800 LifeCyleVC[5502:834637] -[XibViewController viewDidLayoutSubviews]
2019-01-18 16:32:07.922041+0800 LifeCyleVC[5502:834637] -[XibViewController viewDidAppear:]
方式三輸出:
2019-01-21 18:35:39.242503+0800 LifeCyleVC[50009:3700866] +[NextViewController initialize]
2019-01-21 18:35:39.246208+0800 LifeCyleVC[50009:3700866] -[NextViewController initWithCoder:]
2019-01-21 18:35:39.246431+0800 LifeCyleVC[50009:3700866] -[NextViewController awakeFromNib]
2019-01-21 18:35:39.256965+0800 LifeCyleVC[50009:3700866] -[NextViewController loadView]
2019-01-21 18:35:39.257161+0800 LifeCyleVC[50009:3700866] -[NextViewController viewDidLoad]
2019-01-21 18:35:39.259448+0800 LifeCyleVC[50009:3700866] -[NextViewController viewWillAppear:]
2019-01-21 18:35:39.266274+0800 LifeCyleVC[50009:3700866] -[NextViewController viewWillLayoutSubviews]
2019-01-21 18:35:39.266608+0800 LifeCyleVC[50009:3700866] -[NextViewController viewDidLayoutSubviews]
2019-01-21 18:35:39.778369+0800 LifeCyleVC[50009:3700866] -[NextViewController viewDidAppear:]
方式四輸出:
2019-01-18 17:19:47.437557+0800 LifeCyleVC[6466:1012816] +[NSCoderViewController initialize]
2019-01-18 17:19:47.437860+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController initWithCoder:]
2019-01-18 17:19:47.438482+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController loadView]
2019-01-18 17:19:47.438682+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController viewDidLoad]
2019-01-18 17:19:47.440091+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController viewWillAppear:]
2019-01-18 17:19:47.441523+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController viewWillLayoutSubviews]
2019-01-18 17:19:47.441673+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController viewDidLayoutSubviews]
2019-01-18 17:19:47.441743+0800 LifeCyleVC[6466:1012816] -[ViewController viewWillLayoutSubviews]
2019-01-18 17:19:47.441821+0800 LifeCyleVC[6466:1012816] -[ViewController viewDidLayoutSubviews]
2019-01-18 17:19:47.942351+0800 LifeCyleVC[6466:1012816] -[NSCoderViewController viewDidAppear:]
視圖銷毀調(diào)用方法:
2019-01-21 17:33:44.561425+0800 LifeCyleVC[49067:3464394] -[ViewController viewWillDisappear:]
2019-01-21 17:33:44.569643+0800 LifeCyleVC[49067:3464394] -[ViewController viewWillLayoutSubviews]
2019-01-21 17:33:44.569801+0800 LifeCyleVC[49067:3464394] -[ViewController viewDidLayoutSubviews]
2019-01-21 17:33:45.073069+0800 LifeCyleVC[49067:3464394] -[ViewController viewDidDisappear:]
2019-01-21 17:33:45.073069+0800 LifeCyleVC[49067:3464394] -[ViewController dealloc]
+(void)load
https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
當(dāng)一個(gè)類或者類別被加載到OC運(yùn)行時(shí)時(shí)調(diào)用,每個(gè)類、類別的+load方法,在程序運(yùn)行時(shí)只會(huì)加載一次
- 先加載父類的+load方法,再加載子類的+load方法,不同的類的+load方法調(diào)用和編譯時(shí)添加的順序一致(Compile Sources)
- 先加載類的+load方法(包括子類,也就是說子類的+load方法在類別的+load方法調(diào)用之前調(diào)用),再加載類別的+load方法,不同的類別的+load方法調(diào)用和編譯時(shí)添加的順序一致(Compile Sources)
- 子類的+load方法未實(shí)現(xiàn)并不會(huì)調(diào)用父類的+load方法
概括來(lái)說:類-->子類-->類別
+(void)initialize
https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?language=occ
Initializes the class before it receives its first message.
初始化類,在類第一次收到消息之前調(diào)用
- 先調(diào)用父類的initialize,再調(diào)用子類的initialize方法
- runtime發(fā)送initialize消息是線程安全的,因?yàn)閕nitialize是在類發(fā)送第一條消息之前調(diào)用,并且任何線程都必須在完成initialize方法之后再向類發(fā)送消息。
- 若是子類沒有實(shí)現(xiàn)initialize方法,則會(huì)調(diào)用父類initialize方法,所以一個(gè)父類的initialize可能被多次調(diào)用,子類實(shí)現(xiàn)initialize方法時(shí),會(huì)覆蓋父類initialize方法.
- 當(dāng)有多個(gè)Category都實(shí)現(xiàn)了initialize方法,會(huì)覆蓋類中的方法,只執(zhí)行一個(gè)(會(huì)執(zhí)行Compile Sources 列表中最后一個(gè)Category 的initialize方法)
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
Returns a newly initialized view controller with the nib file in the specified bundle.
從指定的nib文件中初始化視圖控制器。
- (instancetype)init
https://developer.apple.com/documentation/objectivec/nsobject/1418641-init?language=occ
Implemented by subclasses to initialize a new object (the receiver) immediately after memory for it has been allocated.
由子類實(shí)現(xiàn)初始化一個(gè)新的對(duì)象(接收者)后立即內(nèi)存分配
- (instancetype)initWithCoder:(NSCoder *)aDecoder
當(dāng)從nib或者storyboard中初始化對(duì)象時(shí),則會(huì)調(diào)用該方法??梢杂迷摲椒▉?lái)重新定義我們?cè)趎ib中已經(jīng)設(shè)置的各項(xiàng)屬性。
- 遵循NSCoding協(xié)議的對(duì)象調(diào)用才能調(diào)用該方法進(jìn)行初始化對(duì)象。
- (void)awakeFromNib
https://developer.apple.com/documentation/objectivec/nsobject/1402907-awakefromnib?language=occ
Prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file.
當(dāng)從nib文件或者Interface Builder archive中加載視圖調(diào)用
- 在初始化的過程中,每個(gè)對(duì)象都會(huì)使用它合適的方法進(jìn)行初始化。遵循NSCoding協(xié)議的對(duì)象調(diào)用initWithCoder:進(jìn)行初始化,不遵循NSCoding協(xié)議的其他對(duì)象調(diào)用init方法初始化。
- 該方法必須在對(duì)象被加載和初始化之后調(diào)用
- 當(dāng)一個(gè)對(duì)象調(diào)用awakeFromNib方法時(shí),要確保所有的outlet和事件關(guān)聯(lián)都被建立。
- (void)loadView
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview?language=occ
Creates the view that the controller manages.
創(chuàng)建視圖控制器的視圖
如果視圖控制器關(guān)聯(lián)的是nib文件,那么就從nib文件中加載view,如果沒有關(guān)聯(lián)nib文件,則該方法創(chuàng)建一個(gè)UIView對(duì)象。
- (void)viewDidLoad
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload?language=occ
Called after the controller's view is loaded into memory.
當(dāng)一個(gè)控制器的視圖被加載到內(nèi)存中時(shí)調(diào)用
- (void)viewWillAppear:(BOOL)animated
Notifies the view controller that its view is about to be added to a view hierarchy.
通知視圖控制器,視圖將要被添加到視圖層次結(jié)構(gòu)中。
你可以覆蓋這個(gè)方法執(zhí)行自定義任務(wù)與視圖顯示相關(guān),例如你可以在此方法中改變狀態(tài)欄的風(fēng)格。
- (void)viewWillLayoutSubviews
Called to notify the view controller that its view is about to layout its subviews.
通知視圖控制器將要布局它的子視圖時(shí)調(diào)用。
- (void)viewDidLayoutSubviews
Called to notify the view controller that its view has just laid out its subviews.
通知視圖控制器剛剛布局好子視圖時(shí)調(diào)用。
- (void)viewDidAppear:(BOOL)animated
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621423-viewdidappear?language=objc
Notifies the view controller that its view was added to a view hierarchy.
通知視圖控制器它的視圖已經(jīng)加到視圖層次結(jié)構(gòu)中了。
- (void)viewWillDisappear:(BOOL)animated
Notifies the view controller that its view is about to be removed from a view hierarchy.
通知視圖控制器視圖將要從它的視圖層次結(jié)構(gòu)中移除。
- (void)viewDidDisappear:(BOOL)animated
Notifies the view controller that its view was removed from a view hierarchy.
通知視圖控制器視圖已經(jīng)從它的視圖層次結(jié)構(gòu)中移除。
- (void)dealloc
https://developer.apple.com/documentation/objectivec/nsobject/1571947-dealloc?language=occ
Deallocates the memory occupied by the receiver.
釋放接收器占用的內(nèi)存。
結(jié)語(yǔ)
由于筆者能力有限,若文章中有什么錯(cuò)誤或者需要補(bǔ)充的部分,希望大家不吝賜教,非常感謝。