移動設備的屏幕有限,所有的東西都需要放到一個單一窗口組成的單一界面顯示,在ios中體現為視圖切換(在《ios – 視圖》中已經說明了視圖),當一個視圖替換掉另一個視圖的時候,會經常使用動畫效果,這個任務就是交給視圖管理器來完成的。
ios5之後應用程序窗口有一個根視圖控制器(rootViewController),當不為rootViewController賦值時,會出現“Application windows are expected to have a root view controller at the end of application launch”警告。
1. 視圖控制器的實例化方式
視圖控制器的實例化也有幾種方式:
第一種: 代碼,也是我最喜歡的一種,不是因為它簡單,是因為使用代碼會使得程序的結構變得清晰簡單 更易懂。
[[ViewController alloc] init];
[[ViewController alloc]initWithNibName:@"xibName" bundle:nil];
第二種:代理類加載xib
1 . xib文件裡面需要一個ViewController,並將xib的 File's Owner的Identity inspector中的class設置為應用程序代理類。
2 . 代理類中添加一個ViewController插座變量並連接。
3 . 在application:didFinishLaunchingWithOptions:方法中加載xib文件。
第三種:串聯圖
2.視圖控制器如何創建視圖
UIViewController中有loadView這個方法,默認情況下,自己的視圖控制器並沒有重寫這個方法,本人測試過,當第一次訪問view這個屬性的時候,就會自動調用loadView這個方法,重寫這個方法,代碼如下:
- (void)loadView{
self.view = [[UIView alloc] init];
}
跟不重寫一樣的效果,所以本人就猜想UIViewController中loadView這個方法也是如此實現(沒有使用xib的情況下),歡迎指正。
3.view的生命周期
UIViewController中聲明如下方法:
復制代碼
//加載視圖
- (void)loadView;
//j將要卸載視圖
- (void)viewWillUnload NS_DEPRECATED_IOS(5_0,6_0);
//已經卸載視圖
- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0);
//已經加載
- (void)viewDidLoad;
//視圖將要顯示
- (void)viewWillAppear:(BOOL)animated;
//視圖已經顯示
- (void)viewDidAppear:(BOOL)animated;
//視圖將要隱藏
- (void)viewWillDisappear:(BOOL)animated;
//視圖已經隱藏
- (void)viewDidDisappear:(BOOL)animated;
//將要調用layoutSubviews
- (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0);
//已經調用layoutSubviews
- (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0);
復制代碼
可以重寫這些方法進行生命生命周期的管理。
4.旋轉
視圖控制器的一個主要任務就是知道如何旋轉視圖,有兩種不同旋轉:
抵消旋轉
應用的旋轉是為了抵消設備方向的旋轉,從而應用可以根據用戶如何手持設備而正確的顯示。抵消旋轉的挑戰僅僅在於屏幕不是正方形,這意味著,如果應用旋轉90度,界面不再適合屏幕,必須做出改變進行抵消。
強制旋轉
當某個特定的視圖出現在上界面上時應用進行旋轉,或者在應用啟東時,為了告訴用戶需要旋轉設備才能正確顯示視圖。這是很常見的,因為界面是特地的設計的,而屏幕並不是正方形,所以事實上只能顯示某一特定的模式(豎屏或橫屏)。
為了支持旋轉,視圖控制器需要做的事就是重寫shouldAutorotateToInterfaceOrientation:,傳入的參數是當前設備的方向,是如下之一:
UIInterfaceOrientationPortrait Home健在下方
UIInterfaceOrientationPortraitUpsideDown Home健在下方
UIInterfaceOrientationLandscapeLeft Home健在左邊
UIInterfaceOrientationLandscapeRight Home健在右邊
返回YES允許所有方向旋轉,否則返回NO,如果沒有重寫這個方法,默認是對UIInterfaceOrientationPortrait 返回YES,而其他方向返回NO的,必須對某些方向返回YES。(沒有UIViewController屬性可以設置為視圖控制器可旋轉的方向,只能重寫這個方法)。
iOS 5有一個新特性,就是shouldAutorotateToInterfaceOrientation可以動態的實現, 使用attemptRotationToDeviceOrientation這個方法
該方法的使用場景是 interface orientation和device orientation 不一致,但希望通過重新指定 interface orientation 的值,立即實現二者一致;如果這時只是更改了支持的 interface orientation 的值,沒有調用attemptRotationToDeviceOrientation,那麼下次 device orientation 變化的時候才會實現二者一致,關鍵點在於能不能立即實現。
舉個例子:
假設當前的 interface orientation 只支持 Portrait,如果 device orientation 變成 Landscape,那麼 interface orientation 仍然顯示 Portrait;
如果這時我們希望 interface orientation 也變成和 device orientation 一致的 Landscape,以iOS 6 為例,需要先將 supportedInterfaceOrientations 的返回值改成Landscape,然後調用 attemptRotationToDeviceOrientation方法,系統會重新詢問支持的 interface orientation,已達到立即更改當前 interface orientation 的目的。
旋轉事件
可以通過視圖控制器的interfaceOrientation屬性知道當前界面的方向, UIViewController的子類可以重寫下列方法,以便在旋轉的前後收到通知:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation