View Controller Programming Guid for iOS 筆記

 

1.View Controller 基礎
1.1 View Controller 分類
ViewController分爲container view controller 和content view controller兩種類型。
這兩種類型只是用途不一樣,前者做爲一個容器容納其餘的view controller,後者用來顯示內容,代碼上面區別不大。前者包括UINavigationViewController、 UITabBarViewController等,後者包括UITabViewController等。對於container而言,childViewControllers數組存放了全部的childViewController。viewController的父子關係與view的父子關係不同,以UITabBarViewController爲例,它能夠有兩個childViewController,但這兩個childViewController的view,其subview並非UITabBarViewController的view的sub view。編程

1.2顯示一個ViewController的內容有如下幾種方法
(1)將controller做爲window的root controller
(2)將controller做爲一個container controller的孩子
(3)present
不該該直接的將一個controller的view,放到另外一個controller的子view裏面,這樣會引發問題。數組

2. 在App中使用View Controller
2.1 使用Story Board
2.2 用編程的方式顯示View Controller的內容app

3.建立自定義的Content View Controller
3.1 使用Storyboard來實現本身的View Controller
當使用Storyboard時:
(1)iOS自動初始化你的view controller
(2)須要重載awakeFromNib來完成初始化
(3)在IB裏面建立view體系已經其餘相關聯對象。

當使用編程方式來設計view controller時
(1)使用alloc 和init對view controller進行初始化
(2)建立自定義的初始化函數進行初始化
(3)重載loadView來建立和配置view體系。

4.View Controller資源管理
4.1 初始化View Controller
4.1.1 初始化來自Storyboard的View Controller
執行順序爲
- (id)initWithCoder:(NSCoder *)decoder
- (void)awakeFromNib
4.1.2 使用編程方式初始化View Controller
使用自定義的初始化函數來進行初始化,該函數應該調用super 的init函數

4.2 當View Controller的view被訪問時,View Controller初始化它的view體系
執行順序爲:
1. view controller調用它的loadView函數。在默認的loadView函數中,若view controller與storyboard是關聯的,loadView函數從storyboard中建立view對象,若view controller不與storyboard關聯,loadView函數建立一個UIView對象,並賦值給controller的view屬性。
2. view controller調用它的viewDidLoad函數,從而容許子類作一些額外的加載工做。

4.2.1 從storyboard中加載Controller的view對象
4.2.2 用編程方式建立view對象
若是不用storyboard來建立Controller的view對象,那麼應該重載viewController的loadView方法,如下面的步驟來實現:
(1)建立view controller的root view對象。
(2)建立子view,並把他們add到root view中
(3)實現viewWillLayoutSubview和viewDidLayoutSubview來調整subviews的size
(4)將root view賦值給viewController的view屬性ide

4.3 有效的管理內存
在iOS 6以後 ,在didReceiveMemoryWarning函數中將手動self.view賦值爲ni來釋放內
在iOS 6之前, 系統會在調用了didReceiveMemoryWarning以後將view釋放,而且調用viewWillUnload 和viewDidUnload函數 。
5.對顯示有關的通知進行響應
當view顯示出來以前,viewWillAppear會被調用
當view顯示出來以後,viewDidAppear會被調用
能夠在appear函數 中使用isBeingPresented能夠判斷該viewController是不是被present出來,使用isMovingToParentViewController函數能夠判斷該viewController是否由於被做爲孩子加到一個容器controller裏面而顯示出出來。函數

當view消失以前,viewWillDisappear會被調用
當view消失以後’,viewDidDisappear會被調用
在disappear函數中使用isBeingDismissed能夠判斷該viewController是不是被dismiss掉,使用isMovingFromParentViewController來判斷是不是從parent view controller中移除。佈局

6.改變View Controller的view的大小
6.1 view controller是怎樣參與到view 佈局過程當中的
當view controller的view的size 改變時,它的subviews將被從新定位來適應新的空間。在view的size改變時,如下過程將發生:
(1)view controller的view 被改變爲新的size
(2)若是沒有用auto layout,subviews根據它們的autoresizing mask來改變大小。
(3)view controller的viewWillLayoutSubviews被調用
(4)view controller的view的layoutSubviews被調用,若是使用了auto layout,…
(5)viewController的viewDidLayoutSubviews被調用
理想狀況下,subviews們本身執行了重定位相關的工做,若是須要本身調整subviews的位置,能夠重載layoutSubview來調整那些不能被經過resizing mask自動定位的sub view。動畫

7.使用響應者鏈中的View Controller
8.支持多個方向
8.1 iOS6之後的處理方式
當UIKit收到一個轉向的通知時,它使用UIApplication 對象和app的root view controller來決定是否支持新的方向。若是兩個對象都贊成新的方向,則轉向,不然通知被忽略。
當有一個viewController被present出來以後,這個被present出來的view controller被用來代替root view controller來決定是否轉向,同時,這個presented controller可使用一個預置的方向。
view controller使用函數- (NSUInteger)supportedInterfaceOrientations來聲明支持的方向,使用preferredInterfaceOrientationForPresentation函數來聲明默認的presented controller的方向。

若是但願暫時禁用自動轉向,重載最頂層的view controller的shouldAutorotate函數來返回NO,這樣就不會自動轉向。spa

8.2 iOS6之前的處理方式
使用的函數不同,但機制同樣,都是基於root view controller。
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)orientation
{
if ((orientation == UIInterfaceOrientationPortrait) ||
(orientation == UIInterfaceOrientationLandscapeLeft))
return YES;

return NO;
}
8.3 在當前顯示的view controller中響應方向改變
當設備方向改變時,當前顯示的view controller是會收到通知,而且被給予一個機會來執行額外的任務。可使用這些方法來顯示或隱藏views,從新定位views等等,但不要在此時執行耗時操做。比較合適的處理是提供獨特的views來適應不一樣方向,好比彈出一個新的view controller。
通知消息會被髮送給root view controller,root view controller將這些events在須要的時候傳遞給它的孩子,如下是旋轉發送時事件的順序。
(1)window調用root view controller的willRotateToInterfaceOrientation:duration:函數。Container view controllers會降該消息發送給當前顯示的content view controller。能夠在本身的content view controller裏面重載該函數來隱藏某些view或者作些改變。
(2)window調整view controller的view bound。這會致使view 從新佈局subviews,觸發controller的viewWillLayoutSubviews 函數。當這個函數運行時,能夠根據app的 statusBarOrientation屬性來判斷當前的方向。
(3) view controller的willAnimateRotationToInterfaceOrientation:duration:函數被調用設計

(4)發生動畫
(5) didRotateFromInterfaceOrientation: 被調用。container view controller會發送該消息給當前顯示的content view controller。

8.4 建立一個可選的橫屏界面
若是但願在橫屏時提供基於相同數據的不一樣界面,最好的方式是使用兩個單獨的controllers。一個管理橫向界面,一個管理豎向界面。
實現方法爲:
(1)實現兩個view controller,一個只支持橫屏,一個只支持豎屏
(2)註冊UIDeviceOrientationDidChangeNotification 消息,在handler方法裏面,基於當前的方向,present或者dismiss可選的view controller。

8.5 Tips for Implementing Your Rotation Codecode


9.Presenting View Controllers
10.在View Controllers之間進行協調
10.1.使用delegation與其餘controller通訊

10.2 管理controller 數據的指導方針
(1)一個目標view controller引用的數據應該來自其源view controller,除非它是一個自我配置的view controller
(2)老是使用delegation將信息返回其餘controller,content view controller永遠不須要知道源view controller或者不是由它建立出來view controller的信息
(3)避免沒必要要的鏈接到外部的view controller,每一個鏈接表明的依賴,使得它更難改變你的應用程序的設計。

11.使用View Controller的 編輯模式
12.建立自定義Segue
13.建立自定義Container View Controller
13.1 設計本身的Container View Controller
13.2 通用Container View Controller範例
13.3 實現自定義Container View Controller
實現一個容器的目標是可以將其餘view controller的view做爲子樹增長到當前容器controller的view體系中。當增長一個孩子controller的view時,你須要確保事件會被分發到相應的controller中,所以須要顯式的將新的controller做爲容器controller的的孩子。

13.3.1 增長或者移除一個孩子
(1)增長controller的例子
步驟爲:
調用 addChildViewController:將新的controller加到容器的孩子中,該函數會自動調用新controller的 willMoveToParentViewController函數
設置新controller的view的frame
將新的controller的view加到container的view體系中(不必定是container的root view)
調用新controller的didMoveToParentViewController函數
範例代碼爲:

- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.frame = [self frameForContentController]; // 2
[self.view addSubview:self.currentClientView];
[content didMoveToParentViewController:self]; // 3
}
(2)移除controller的孩子
步驟爲:
調用孩子的willMoveToParentViewController:
移除view
調用孩子的removeFromParentViewController ,將孩子從容器中移除,該函數會自動調用didMoveToParentViewController:
範例代碼爲:
- (void) hideContentController: (UIViewController*) content
{
[content willMoveToParentViewController:nil]; // 1
[content.view removeFromSuperview]; // 2
[content removeFromParentViewController]; // 3
}

如下代碼演示了在兩個viewController之間進行切換:
- (void) cycleFromViewController: (UIViewController*) oldC
toViewController: (UIViewController*) newC
{
[oldC willMoveToParentViewController:nil]; // 1
[self addChildViewController:newC];

newC.view.frame = [self newViewStartFrame]; // 2
CGRect endFrame = [self oldViewEndFrame];

[self transitionFromViewController: oldC toViewController: newC // 3
duration: 0.25 options:0
animations:^{
newC.view.frame = oldC.view.frame; // 4
oldC.view.frame = endFrame;
}
completion:^(BOOL finished) {
[oldC removeFromParentViewController]; // 5
[newC didMoveToParentViewController:self];
}];
}
13.3.2 自定義外觀和旋轉回調行爲
13.3.2 創建容器controller的實際建議

相關文章
相關標籤/搜索