一, loadView和viewDidload
在控制器加載view的時候,系統(tǒng)默認做法:訪問self.view如果view==nil就會調(diào)用loadView方法,所以會產(chǎn)生以下需要特別注意的地方:
#import "MyViewController.h"
#import "MyView.h"
@interface MyViewController ()
@end
@implementation MyViewController
//首先系統(tǒng)默認做法,訪問self.view如果view==nil就會調(diào)用loadView方法
//系統(tǒng)底層view的get方法是通知loadView方法創(chuàng)建控制器的view.
//1.判斷當前的控制器是否從StoryBoard加載的.如果是,從StoryBoad當中創(chuàng)建view.
//2.如果不是,還會判斷當前控制器,是否有xib進行描述.如果有,就會從Xib里面創(chuàng)建View
//3.如果也不是xib來描述的,那么它就會給創(chuàng)建一個空的UIView.
/*
* 在開發(fā)當中一旦重寫了loadView,需要自己創(chuàng)建View.
* 重寫loadView一般用在:
* 1.當控制器的view一進來就是顯示一個圖片時
* 2.當控制器一進來就去加載一個網(wǎng)頁時.
* 特別注意:loadView 重寫時不調(diào)用[super loadView]容易訪問到空view;
* 而訪問self.view,會訪問空的view,會導(dǎo)致死循環(huán)exc_bad_access(code = 2....)的錯誤
*/
//若假定不能從storyBoard和xib加載view,重寫loadView如下:
-(void)loadView {
// [super loadView];
// NSLog(@"我執(zhí)行了%s",__func__);
//特別注意:如果view為nil,調(diào)用self.view方法會造成死循環(huán)
// self.view = [[MyView alloc]initWithFrame:self.view.bounds];
//創(chuàng)建imageV
UIImageView *imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Default"]];
imageV.frame = [UIScreen mainScreen].bounds;
// 特別注意: 此處調(diào)用self.view會在view沒賦值時候?qū)е滤姥h(huán)
// imageV.frame = self.view.bounds;
// //如果一個控件它的父控件不能夠接收事件,那么它里面的子控件都不能夠接收事件.
imageV.userInteractionEnabled = YES;
//給view屬性賦值
self.view = imageV;
}
//loadView是當?shù)谝淮问褂每刂破鱒iew的調(diào)用.調(diào)用控制器view的get方法
//以下為模擬系統(tǒng)實現(xiàn)view方法的原理,注意如果view為空則會調(diào)用loadView方法加載view
//-(UIView *)view {
// if (_view == nil) {
// [self loadView];
// }
// return _view;
//}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"%@",self.view);
UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn.frame = CGRectMake(50, 100, 50, 50);
[self.view addSubview:btn];
}
二, viewDidUnload
1.什么時候被調(diào)用?
iOS設(shè)備的內(nèi)存是極其有限的,如果應(yīng)用程序占用的內(nèi)存過多的話,系統(tǒng)就會對應(yīng)用程序發(fā)出內(nèi)存警告。UIViewController就會收到didReceiveMemoryWarning消息。didReceiveMemoryWarning方法的默認實現(xiàn)是:如果當前UIViewController的view不在應(yīng)用程序的視圖層次結(jié)構(gòu)(View Hierarchy)中,即view的superview為nil的時候,就會將view釋放,并且調(diào)用viewDidUnload方法
2.有什么作用?
上面說到,發(fā)出內(nèi)存警告且view被釋放的時候就會調(diào)用viewDidUnload方法,所以一般在釋放資源,主要是釋放界面元素相關(guān)的資源,將相關(guān)的實例都賦值為nil
[java] view plain copy
- (void)viewDidUnload {
[super viewDidUnload];
self.name = nil;
self.pwd = nil;
}
3.dealloc也是用來釋放資源的,那跟viewDidUnload有什么關(guān)系?
當發(fā)出內(nèi)存警告調(diào)用viewDidUnload方法時,只是釋放了view,并沒有釋放UIViewController,所以并不會調(diào)用dealloc方法。即viewDidUnload和dealloc方法并沒有任何關(guān)系,dealloc方法只會在UIViewController被釋放的時候調(diào)用
三, 三個方法的關(guān)系:
1.第一次訪問UIViewController的view時,view為nil,然后就會調(diào)用loadView方法創(chuàng)建view
2.view創(chuàng)建完畢后會調(diào)用viewDidLoad方法進行界面元素的初始化
3.當內(nèi)存警告時,系統(tǒng)可能會釋放UIViewController的view,將view賦值為nil,并且調(diào)用viewDidUnload方法
4.當再次訪問UIViewController的view時,view已經(jīng)在3中被賦值為nil,所以又會調(diào)用loadView方法重新創(chuàng)建view
5.view被重新創(chuàng)建完畢后,還是會調(diào)用viewDidLoad方法進行界面元素的初始化