轉自:http://haoxiang.org/page/5/
UIViewController的loadView
用UIViewController有一段時間了,才發現以前對loadView的理解完全不到位。
假如我們用Xcode新建一個View-based Application,在ViewController.m中加上
- (void) loadView {
NSLog(@"loadView Called");
}
再增加viewDidLoad,按照一般的情況,我們會有這樣的Code
- (void) viewDidLoad {
[super viewDidLoad];
UIButton *customButton = [UIButton buttonWith.....
......
[self.view addSubView:customButton];
}
現在打開MainWindow.xib,刪掉其中的ViewController,並在AppDelegate.m的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
里增加ViewController的初始化
viewController = [[XXXViewController alloc] init];
編譯運行就有問題了。Console中不斷的輸出loadView Called!
仔細的閱讀loadView的文檔,才知道loadView不是這么用的。
loadView在每一次使用self.view這個property,並且self.view為nil的時候被調用,用以產生一個有效的self.view。這個接口原本是為了讓我們自定義view用的。在不被subclass實現的情況下,也就是[super loadView]的效果,應該就是產生了一個有效的view,也就是一個空白的view。
在上面這種情況下,loadView被實現為空(只有一條打印語句),而且我們沒有通過XIB初始化ViewController,所以在viewDidLoad被執行時,self.view是為nil的。所以在執行[self.view addSubView:customButton]時,loadView被調用,用來產生一個有效的view,使得self.view不再為nil。罷特,我們錯了(-_-!)。我們的loadView什么也沒有做,於是就出現了上面的情形,不斷的調用一個什么都不做的loadView….
當然,我們只要在loadView中增加一句[super loadView]就沒有問題了。但這並不是Cocoa的設計者所期望的。
loadView僅僅應該在開發者希望自行通過編碼而不是Interface Builder定制view的時候被實現,而且不應該在其中調用[super loadView],你的loadView中應該有self.view = …這樣的行為。
如果僅僅是想要在當前view上增加一些UIButton或是UILabel,應該在viewDidLoad里去做,此時不要實現自己的loadView。
轉自:http://www.cocoachina.com/bbs/simple/?t52059.html
loadView VS viewDidLoad
loadView 和 viewDidLoad 的區別
iPhone開發必不可少的要用到這兩個方法。 他們都可以用來在視圖載入的時候,初始化一些內容。 但是他們有什么區別呢?
viewDidLoad 此方法在view被 addsubWiew后調用。viewDidLoad用於初始化,加載時用到的。 (不論是從xib中加載視圖,還是從loadview生成視圖,都會被調用。)
loadView 此方法在控制器的view為nil的時候被調用。 此方法用於以編程的方式創建view的時候用到。loadView是使用代碼生成視圖的時候,當視圖第一次載入的時候調用的方法。用於使用(寫)代碼來實現控件。用於使用代碼生成控件的函數。如:
- ( void ) loadView {
UIView *view = [ [ UIView alloc] initWithFrame:[ UIScreen
mainScreen] .applicationFrame] ;
[ view setBackgroundColor:_color] ;
self.view = view;
[ view release] ;
}
你在控制器中實現了loadView方法,那么你可能會在應用運行的某個時候被內存管理控制調用。 如果設備內存不足的時候, view 控制器會收到didReceiveMemoryWarning的消息。 默認的實現是檢查當前控制器的view是否在使用。如果它的view不在當前正在使用的view hierarchy里面,且你的控制器實現了loadView方法,那么這個view將被release, loadView方法將被再次調用來創建一個新的view。
UIViewController 的內存管理
在 iOS3.0 后,UIViewController 多了一個叫做 viewDidUnLoad 的方法。
先看下 UIViewController 從創建 view 到展示的流程的幾個函數
-init
-initWithNibName:bundle:
這兩個方法都是初始化一個 vc,但請注意 view 不是這時候載入的
-loadView
-viewDidLoad
當一個視圖准備展現時,vc 首先會判斷 view 是否已經創建否則便通過之前指定的 xib 文件來初始化 view,以及綁定其他關系(若沒有指定 xib 文件,則默認會搜索和 vc 同名的 xib,比如 myNameViewController 就會搜索 myNameViewController.xib 文件)
若是沒有 xib 文件,你就可以在 loadview 中自己手動創建這個 viewControoler 需要的視圖。接下來就是調用到 -viewDidLoad,許多人喜歡在這里做些其他事情,比如做個 http 請求、建立個數組啥的。這里若不處理正確,-viewDidUnload 激活時內存就容易泄露了,稍后提到。
-view()appear
-view()disappear
這幾個方法就不解釋了
-viewDidUnload
該方法在收到內存警告,同時該視圖並不在當前界面顯示時候會被調用,此時該 controller 的 view 已經被釋放並賦值為 nil。
接下來你要做的是
把實例變量的子視圖釋放(IBOulet 的,以及自己添加的)
其他實例變量,比如之前在 -viewDidLoaded 中實例的數據數組、http 請求釋放掉
因為當該 viewController 再次被激活准備顯示時(比如 navigationControler 返回到上一級),vc 發現自己的 view 為空后會重復之前的流程直到把 view 給創建起來。若沒將自己額外添加的子視圖,各種類實例變量釋放,這里便會重新再次創建。
於是,內存泄露了。
注意iphone開發中的這兩個函數viewWillAppear和viewDidAppear
每當視圖准備在屏幕上顯示,或者視圖已在屏幕上完全顯示時,將調用這兩個方法。
viewWillAppear:方法更新准備顯示的視圖的信息。調用時,視圖可能還沒有被加載。
使用viewDidAppear:來觸發視圖完全顯示在屏幕上之后的行為,例如任何動畫。
viewdidload是當程序第一次加載view時調用,以后都不會用到,而viewDidAppear是每當切換到view時就調用。
loadView和viewDidLoad方法。假設不使用xib文件對視圖布局,那么loadView方法必須設置屏幕,並對任何子視圖布局。每當繼承一個具體的子類,例如UITableViewController或UITabBarController時,務必調用[super loadView]或者實現viewDidLoad。這樣一來,在進行定制之前,父類可以對屏幕進行適當的設置。當代碼基於具體的子類時,蘋果的文檔和示例代碼鼓勵使用viewDidLoad。
viewDidLoad 此方法只有當view從nib文件初始化的時候才被調用。viewDidLoad用於初始化,加載時用到的。
loadView 此方法在控制器的view為nil的時候被調用。 此方法用於以編程的方式創建view的時候用到。loadView是使用代碼生成視圖的時候,當視圖第一次載入的時候調用的方法。用於使用(寫)代碼來實現控件。用於使用代碼生成控件的函數。
viewDidLoad ,不論是從xib中加載視圖,還是從loadview生成視圖,都會被調用。