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。
總結:用于自定義View.在view為nil時會在self.view調用.重新通過[super view]創建.重寫時手動創建View.