ViewController 詳解,viewcontroller詳解

來源:互聯網
上載者:User

ViewController 詳解,viewcontroller詳解
 

一、頁面跳轉
1、利用UINavigationController,調用pushViewController,進行跳轉;這種採用壓棧和出棧的方式,進行Controller的管理。調用popViewControllerAnimated方法可以返回。 

    PickImageViewController *ickImageViewController = [[PickImageViewController alloc] init]; 
    [self.navigationController pushViewController: ickImageViewController animated:true]; 
    [ickImageViewController release]; 


2、利用UIViewController自身的presentViewController進行跳轉;調用dismissViewControllerAnimated方法可以返回。 
    PickImageViewController *ickImageViewController = [[PickImageViewController alloc] init]; 

[self presentViewController:ickImageViewController

                       animated:YES

                     completion:^(void){

                         // Code

                     

                     }];

 //返回 [self dismissViewControllerAnimated:YES

                             completion:^(void){

                                 // Code

                             }];

新介面的差別是提供了一個參數,允許你傳入一個block。這個block的回調方法在VC的viewWillDisappear方法後調用。也就是被隱藏的VC對象被釋放後運行回調。

二、生命週期

當一個視圖控制器被建立,並在螢幕上顯示的時候。 代碼的執行順序
1、 alloc                              建立對象,分配空間
2、init (initWithNibName)  初始化對象,初始化資料
3、loadView          從nib載入視圖 ,通常這一步不需要去幹涉。除非你沒有使用xib檔案建立視圖
4、viewDidLoad       載入完成,可以進行自訂資料以及動態建立其他控制項
5、viewWillAppear                視圖將出現在螢幕之前,馬上這個視圖就會被展現在螢幕上了
6、viewDidAppear       視圖已在螢幕上渲染完成當一個視圖被移除螢幕並且銷毀的時候的執行順序,這個順序差不多和上面的相反
1、viewWillDisappear            視圖將被從螢幕上移除之前執行
2、viewDidDisappear     視圖已經被從螢幕上移除,使用者看不到這個視圖了
3、dealloc                            視圖被銷毀,此處需要對你在init和viewDidLoad中建立的對象進行釋放

關於viewDidUnload :在發生記憶體警告的時候如果本視圖不是當前螢幕上正在顯示的視圖的話,  viewDidUnload將會被執行,本視圖的所有子視圖將被銷毀,以釋放記憶體,此時開發人員需要手動對viewLoad、viewDidLoad中建立 的對象釋放記憶體。 因為當這個視圖再次顯示在螢幕上的時候,viewLoad、viewDidLoad 再次被調用,以便再次構造視圖。

三、view的載入過程

文字說明在表述流程的時候總是很費力的,我又找到了如下的兩張圖

跟隨如下文字理解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會從StroyBoards中找或者調用其預設的loadView,預設的loadView返回一個空白的UIView對象。

注意第一步,ViewController是判斷子類是否重寫了loadView,而不是判斷調用子類的loadView之後 ViewController的View是否為空白。就是說,如果子類重寫了loadView的話,不管子類在loadView裡面能否擷取到 View,ViewController都會直接調viewDidLoad完成View的載入。

四、view卸載過程圖

跟隨以下文字理解卸載過程:

1 系統發出警告或者ViewController本身調用導致didReceiveMemoryWarning被調用

2 調用viewWillUnload之後釋放View

3 調用viewDidUnload

五、模擬器的調用順序

我構架了這樣一個環境,在該環境中有兩個viewController,姑且命名為A和B,tag分別為1和2,A控製程序啟動的時候即載入的介面,在A中放一個按鈕,按下後會通過segue來調用到介面B;B 中頁放一個按鈕,通過執行

[self dismissModalViewControllerAnimated:YES];

來返回介面A

然後檢測所有的函數調用,依次如下

載入A的時候依次調用

 

1 initWithCoder

1 loadView //如果說你進行了重寫,會在這裡調用,這一步可以參考下文

1 viewDidLoad

1 viewWillAppear

1 viewWillLayoutSubviews

1 viewDidLayoutSubviews

1 viewDidAppear

 

切換至B的時候依次調用

 

2 initWithCoder             //先將2初始化

1 prepareForSegue       //調用1的準備過度的函數,所以在該函數中可以對介面B的一些相關屬性進行賦值

2 loadView    //如果這裡進行了重寫

2 viewDidLoad              //2介面載入

1 viewWillDisappear

2 viewWillAppear

2 viewWillLayoutSubviews

2 viewDidLayoutSubviews

2 viewDidAppear

1 viewDidDisappear

 

從B切換回A的時候依次調用

 

2 viewWillDisappear

1 viewWillAppear

1 viewDidAppear

2 viewDidDisappear

2 dealloc

 

順序總結下來載入依次為:載入 - 顯示 - 布局

完成順序依次為:完成布局 - 完成顯示  - 完成載入

 

小註:-(void)loadView;函數如果重寫,下面是一個可能的demo

 

-(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 are expected to have a root view controller at the end of application launch

具體執行順序為:代碼執行了initWithCoder之後直接調用了三次loadView函數,並且沒有調用其它函數(包括viewDidLoad 、viewWillDisappear、viewWillLayoutSubviews)

疑問:

暫不清楚為什麼會調用三次,我的猜測是:上述三個函數分別檢測了一遍view是否存在,發現不存在,所以各自調用了一遍viewLoad,最後發現依然不存在,所以上述三個函數分別返回了失敗,載入完成

但矛盾的地方是:為什麼上述三個函數本身沒有執行到?底層到底做了什嗎?

 

六、view和ViewController的建立階段,關於什麼時候應該幹什麼

1、init

Allocating critical data structures required by your view controller

不要出現建立view的代碼。良好的設計,在init裡應該只有相關資料的初始化,而且這些資料都是比較關鍵的資料。init裡不要掉self.view,否則會導致viewcontroller建立view。(因為view是lazyinit的)。

2、loadView

Creating your view objects

只初始化view,一般用於建立比較關鍵的view如tableViewController的 tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super  loadView前),最好也不要初始化一些非關鍵的view。如果你是從nib檔案中建立的viewController在這裡一定要首先調用 super的loadView方法,但建議不要重載這個方法。

3、viewDidLoad 

Allocating or loading data to be displayed in your view

這時候view已經有了,最適合建立一些附加的view和控制項了。有一點需要注意的是,viewDidLoad會調用多次(viewcontroller可能多次載入view,參見圖2)。

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

5、viewDidAppear 一般用於顯示後,在切換動畫後,如果有需要的操作,可以在這裡加入相關代碼。

6、viewDidUnload 

Releasing references to view objects

Releasing data that is not needed when your view is not displayed

這時候viewController的view已經是nil了。由於這一般發生在記憶體警告時,所以在這裡你應該將那些不在顯示的view釋放了。比 如你在viewcontroller的view上加了一個label,而且這個label是viewcontroller的屬性,那麼你要把這個屬性設定 成nil,以免佔用不必要的記憶體,而這個label在viewDidLoad時會重新建立。

7、dealloc

Releasing critical data structures required by your view controller

七、幾點備忘:

1、按結構可以對iOS的所有ViewController分成兩類:

1)、。主要用於展示內容的ViewController,這種ViewController主要用於為使用者展示內容,並與使用者互動,如UITableViewController,UIViewController

2)、用於控制和顯示其他ViewController的ViewController。這種ViewController一般都是一個 ViewController的容器。如UINavigationController,UITabbarController。它們都有一個屬 性:viewControllers。其中UINavigationController表示一種Stack式結構,push一個 ViewController或pop一次,因此後一個ViewController一般會依賴前一個ViewController。而 UITabbarController表示一個Array結構,各個ViewController是並列的。

第一種ViewController會經常被繼承,用來顯示不同的資料給使用者。而第二種很少被繼承,除非你真的需要自訂它。

2、由於Controller載入View時,會自動將一些View對象指向其對應的IBOutlet變數。

所以當view被卸載時我們必須在viewDidUnload將這些變數release掉,ViewController不會自動做這件事。

具體做法是將變數設定為空白,(注意和dealloc中將變數release的區別)注意此時Controller的view屬性是空的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.