iOS學習筆記02—View Controller的生命週期

iOS學習筆記02—View Controller的生命週期

一、ViewController

View Controller用於管理應用的資源,包括管理與之關聯的View,與其他ViewController通信和協調。爲了保證程序的高效運行,View Controller總是在需要的時候才加載View(通常被稱爲lazyload),並在不需要或者內存告警的時候卸載視圖。

 

二、ViewController的生命週期

用一個自定義的ViewController做測試類名TestViewController,重寫如下方法並加上日誌信息:

- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

    self = [super initWithNibName:nibNameOrNilbundle:nibBundleOrNil];

    if (self) {

        // Custom initialization

        NSLog(@"initWithNibName");

    }

    return self;

}

-(void)dealloc{

    [super dealloc];

    NSLog(@"dealloc");

}

-(void)viewDidAppear:(BOOL)animated{

   

    [super viewDidAppear: animated];

    NSLog(@"viewDidAppear");

}

 

-(void)viewDidDisappear:(BOOL)animated{

    [super viewDidDisappear: animated];

    NSLog(@"viewDidDisappear");

}

 

-(void)viewDidLayoutSubviews{

    [super viewDidLayoutSubviews];

    NSLog(@"viewDidLayoutSubviews");

}

 

-(void)viewDidLoad{

    [super viewDidLoad];

    NSLog(@"viewDidLoad");

}

 

-(void)viewDidUnload{

    [super viewDidUnload];

    NSLog(@"viewDidUnload");

}

 

-(void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear: animated];

    NSLog(@"viewWillAppear");

}

 

-(void)viewWillDisappear:(BOOL)animated{

    [super viewWillDisappear: animated];

    NSLog(@"viewWillDisappear");

}

-(void)viewWillLayoutSubviews{

    [super viewWillLayoutSubviews];

    NSLog(@"viewWillLayoutSubviews");

}

 

-(void)viewWillUnload{

    [super viewWillUnload];

    NSLog(@"viewWillUnload");

}

 

-(void)loadView{

    [super loadView];

   NSLog(@"loadView");

}

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can berecreated.

    NSLog(@"didReceiveMemoryWarning");

}

 

在另外一個ViewController中調用代碼如下:

- (IBAction)buttonPressed:(id)sender {

   

    TestViewController *viewController =[[TestViewController alloc] initWithNibName: @"TestViewController" bundle: nil];

   

    [self.navigationController pushViewController:viewController animated: YES];

    [viewController release];

}

 

點擊button,然後按導航欄的[返回],打印的日誌如下,顯示了各方法其調用順序:

2013-03-27 16:58:48.277StudyInit[1659:11303] initWithNibName

2013-03-27 16:58:48.279StudyInit[1659:11303] loadView

2013-03-27 16:58:48.280StudyInit[1659:11303] viewDidLoad

2013-03-27 16:58:48.281StudyInit[1659:11303] viewWillAppear

2013-03-27 16:58:48.284StudyInit[1659:11303] viewWillLayoutSubviews

2013-03-27 16:58:48.285StudyInit[1659:11303] viewDidLayoutSubviews

2013-03-27 16:58:48.637StudyInit[1659:11303] viewDidAppear

2013-03-27 16:58:50.158StudyInit[1659:11303] viewWillDisappear

2013-03-27 16:58:50.511StudyInit[1659:11303] viewDidDisappear

2013-03-27 16:58:50.512StudyInit[1659:11303] dealloc

 

iOS 模擬器的菜單裏選 硬件->模擬內存警告,打印的日誌信息如下:

2013-03-28 10:03:21.225StudyInit[556:11303] Received memory warning.

2013-03-28 10:03:21.226StudyInit[556:11303] didReceiveMemoryWarning

 

 

三、詳細解釋一下:

1initWithNibName:

初始化ViewController本身。

init中應該只有相關數據的初始化,而且這些數據都是比較關鍵的數據,不要出現創建view的代碼,也不要調self.view,否則會導致ViewController創建view。

如果是外部通過調用initWithNibName:bundle指定nib文件名的話,ViewController記載此nib來創建View。

如果initWithNibName:bundle的name參數爲nil,則ViewController會通過以下兩個步驟找到與其關聯的nib。

1)如果ViewController的類名以“Controller”結尾,例如ViewController的類名是MyViewController,則查找是否存在MyView.nib;

2)找跟ViewController類名一樣的文件,例如MyViewController,則查找是否存在MyViewController.nib。

 

2loadView:

只初始化view,一般用於創建比較關鍵的view如tableView Controller的tabView,UINavigationController的navgationBar,不可調用view的getter(在掉super loadView前),最好也不要初始化一些非關鍵的view。

需要用到view,比如調用了view的getter方法時,在getter裏會先判斷view是否創建,如果沒有創建,那麼會調用loadView來創建view,並賦值給ViewController的view屬性,在loadView之前view是nil

如果子類沒有重寫的loadView,則ViewController會從StroyBoards中找或者調用其默認的loadView,默認的loadView返回一個空白的UIView對象。

View Controller是判斷子類是否重寫了loadView,而不是判斷調用子類的loadView之後ViewControllerView是否爲空。就是說,如果子類重寫了loadView的話,不管子類在loadView裏面能否獲取到ViewViewController都會直接調viewDidLoad完成View的加載。

如果手工維護views,必須重載該方法。

如果使用IB維護views,不能重載該方法。

If you use Interface Builder to create your views and initialize the view controller, you must not override this method.

 

3viewDidLoad:

view已經加載到內存中了。適合創建一些附加的view和控件。

 

4viewWillAppear:

view即將顯示,但此時其superView還爲nil,即view還沒有加到任何其他view中,但準備要添加到其他View中了。

在view被添加到superview之前,切換動畫之前調用。在這裏可以進行一些顯示前的處理。比如鍵盤彈出,一些特殊的過程動畫(比如狀態條和navigationbar顏色)

 

5viewWillLayoutSubviews:

view即將佈局其Subviews。比如view的bounds改變了,要調整Subviews的位置,在調整之前要做的一些工作就可以在該方法中實現。

 

6viewDidLayoutSubviews:

view已經佈局其Subviews。比如view的bounds改變了,已經調整Subviews的位置,在調整完成之後要做的一些工作就可以在該方法中實現。

 

7viewDidAppear:

view已經顯示,即已經加到其superView中了。view顯示後,在切換動畫後,如果有需要的操作,可以在這裏加入相關代碼

 

8viewWillDisappear:

view即將從superView中移除,此時還沒有調用removeFromeSuperView。

 

9viewDidDisappear:

view已經從superView中移除了。

 

10dealloc:

view Controller被釋放。

 

需要注意如下幾個方法

viewDidUnloadiOS6廢棄了該方法)

viewWillUnloadiOS6廢棄了該方法)

didReceiveMemoryWarning

內存吃緊時(系統發出警告或者ViewController本身調用導致didReceiveMemoryWarning被調用)。

注意是除當前正在展示的view 所屬 viewController 以外所有已經在內存裏面的viewController 執行 didReceiveMemoryWarning方法,而不是當前viewController 執行 didReceiveMemoryWarning。

 

一個didReceiveMemoryWarning的實現方案:

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Addcode to clean up any of your own resources that are no longer necessary.

    if ([self.view window] == nil)

    {

        // Add code to preserve data stored in the views that might be

        // needed later.

       

        // Add code to clean up other strong references to the view in

        // the view hierarchy.

        self.view = nil;

    }

}

 

一個可能的loadView實現方案

-(void)loadView

{

    CGRect applicationFrame =[[UIScreenmainScreen] applicationFrame];

    UIView *contentView = [[UIViewalloc]initWithFrame:applicationFrame];

    contentView.backgroundColor =[UIColordarkGrayColor];

    self.view = contentView;

   

    UILabel *lab =[[UILabelalloc]initWithFrame:CGRectMake(100, 100, 100, 100)];

    lab.text = @"HelloWorld";

    [self.viewaddSubview:lab];

}

loadView雖然返回值爲空,但必須在函數體內對self.view進行賦值,否則會在建立該界面的時候收到如下的log信息:

Application windows areexpected to have a root view controller at the end of application launch

 

發佈了139 篇原創文章 · 獲贊 47 · 訪問量 62萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章