標籤:
視圖控制器應該在MVC設計模式中扮演控制層(C)的角色,UIViewController的職責對內管理與之關聯的View,對外跟其他UIViewController通訊和協調。一個視圖控制器管理一個視圖(它可以有子視圖),其view屬性指向它所管理的視圖。UIViewController類可以有子類,可以使用一個系統的UIViewController子類或者直接自己建立一個UIViewController的子類。
使用代碼建立控制器和視圖。
開始建立一個基於視窗的Empty Application的項目。
建立一個視圖控制器子類:File–New–New File(Command+N)然後選擇Objective-C class,命名為RootViewController然後在subclass of中輸入UIViewController,單擊Next按鈕儲存。
現在有一個RootViewController類,接著編輯它的代碼。一個視圖控制器負責獲得或建立它自己的視圖。如果視圖控制器手動建立它的視圖,必須重載UIViewController類的loadView方法。下面給視圖設定一個顏色,放一個“Hello World!”標籤在這個視圖中。
@interface RootViewController ()@end@implementation RootViewController-(void) loadView{ // applicationFrame是整個可見地區,不包括狀態列 UIView* view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; //設定view的顏色 view.backgroundColor = [UIColor greenColor]; //添加一個標籤 UILabel* label = [[UILabel alloc] init]; label.text[email protected]"Hello World!"; //自適應大小 ; //置中 label.center = CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds)); //添加到view [view addSubview:label]; //設定self.view = view這樣視圖控制器就可以管理這個視圖了,如果實現了loadView那麼就必須設定self.view self.view = view; }...@end
視圖控制器已經準備好,現在準備使用它。我們要調整一下應用程式的委託類(AppDelegate),在應用程式委託類的標頭檔中,聲明視圖控制器屬性。
@property (strong, nonatomic) RootViewController *rootViewController;
在應用程式委託的實現代碼中,我們匯入”RootViewController.h”,在應用程式委託的application: didFinishLaunchingWithOptions方法中建立新的視圖控制器,並把視圖放到介面中。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //建立視圖控制器 RootViewController* theRVC = [[RootViewController alloc]init]; self.rootViewController = theRVC; //不僅要建立視圖,還必須把視圖放到介面中 [self.window addSubview:self.rootViewController.view]; [self.window makeKeyAndVisible]; return YES;}
編譯並運行應用程式,運行結果如所示。
還有一種簡單的方法是使用UIWindow的rootViewController屬性。這樣就不需要在應用程式委託類的標頭檔中,聲明視圖控制器屬性。也不需要把視圖作為子視圖添加到視窗上。當給一個rootViewController屬性分配一個UIViewController執行個體時,它會自動獲得UIVIewController的視圖,並使它成為視窗的唯一子視圖。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //建立視圖控制器 RootViewController* theRVC = [[RootViewController alloc]init]; // self.rootViewController = theRVC; //不僅要建立視圖,還必須把視圖放到介面中 //[self.window addSubview:self.rootViewController.view]; //這行代碼與上面注釋掉的兩行代碼的效果是一樣的。 self.window.rootViewController = theRVC; [self.window makeKeyAndVisible]; return YES;}
視窗的根視圖控制器是全域可用的,如果需要擷取根視圖控制器,可以使用下面的代碼:
UIViewController* rootController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
在nib檔案中建立視圖控制器
在nib檔案中設計和維護一個複雜的使用者介面比在代碼中建立更方便、簡單。
Command+N–User Interface–View,命名為View.xib
編輯View.xib,更改File’s Owner的類為RootViewController。這將產生一個view輸出口,並把它串連到視圖上。(在File’s Owner上單擊右鍵,點擊view不放,然後拖動到view上。)
然後修改應用程式委託的相關代碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //使用nib檔案建立視圖控制器 RootViewController* theRVC = [[RootViewController alloc]initWithNibName:@"View" bundle:nil]; self.window.rootViewController = theRVC; [self.window makeKeyAndVisible]; return YES;}
UIViewController的初始化
- 程式請求controller的view
- 如果view在記憶體中,則直接載入。相反,如果不存在,則UIViewController調用loadView方法
- loadView方法執行如下操作:
- 如果你重載了這個方法,則必須建立必要的view並且將一個非nil值傳給UIViewController的view屬性。
- 如果你沒有重載這個函數,UIViewController會預設使用UIViewController的nibName和nibBundle屬性嘗試從nib檔案載入view。如果沒有找到nib檔案,則ViewController會通過以下兩個步驟找到與其關聯的nib。
A 如果類名包含Controller,例如ViewController的類名是MyViewController,則尋找是否存在MyView.nib;
B 找跟ViewController類名一樣的檔案,例如MyViewController,則尋找是否存在MyViewController.nib。
- 如果沒有可用的nib檔案,那麼它建立一個空的UIView作為它的view。
- UIViewController調用viewDidLoad來執行一些載入時任務。
當需要顯示或者訪問view屬性時,view沒有建立的話,VC就會調用loadView方法,在這個時候會建立一個view並將其賦給VC.view屬性。緊接著就會調用VC的viewDidLoad方法,這個時候VC.view保證是有值的,可以做進一步的初始化操作,例如添加一些subview。注意:定製VC時,如果覆蓋loadView方法,不需要調用[super loadView]方法。
UIViewController卸載View的步驟.
對於與之關聯的View,UIViewController總是在需要的時候才載入視圖,並在不需要的時候卸載視圖,所以也同時擔當了管理應用資源的責任。理解UIViewController的生命週期(LifeCycle),能夠有效地管理應用資源。Controller的view最好在需要顯示時再去載入,並且在系統發出記憶體警告時釋放比必要的view及相關的資料對象。UIViewController卸載View的步驟如下:
- 程式收到記憶體警告
- 每個UIViewController調用didReceiveMemoryWarning, 預設會安全地釋放掉view
- 如果UIViewController釋放掉了它的view,它會調用viewDidUnload。可以重載這個方法來進行額外的清理工作。
官方文檔:The View Controller Life Cycle
iOS開發之視圖控制器(UIViewController)