在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ View Controller 容器
與四軸無人機(jī)的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動開發(fā)
Collection View 動畫
截圖測試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動布局工具箱
動畫
為 iOS 7 重新設(shè)計 App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動畫解釋
響應(yīng)式 Android 應(yīng)用
初識 TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項目介紹
Swift 的強大之處
測試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計優(yōu)雅的移動游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動畫
常見的后臺實踐
糟糕的測試
避免濫用單例
數(shù)據(jù)模型和模型對象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計
置換測試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無人機(jī)項目
Mach-O 可執(zhí)行文件
UI 測試
值對象
活動追蹤
依賴注入
Swift
項目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測試 View Controllers
訪談
收據(jù)驗證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場
游戲
調(diào)試核對清單
View Controller 容器
學(xué)無止境
XCTest 測試實戰(zhàn)
iOS 7
Layer 中自定義屬性的動畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫支持
Fetch 請求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過程

View Controller 容器

在 iOS 5 之前,view controller 容器是 Apple 的特權(quán)。實際上,在 view controller 編程指南中還有一段申明,指出你不應(yīng)該使用它們。Apple 對 view controllers 的總的建議曾經(jīng)是“一個 view controller 管理一個全屏幕的內(nèi)容”。這個建議后來被改為“一個 view controller 管理一個自包含的內(nèi)容單元”。為什么 Apple 不想讓我們構(gòu)建自己的 tab bar controllers 和 navigation controllers?或者更確切地說,這段代碼有什么問題:

[viewControllerA.view addSubView:viewControllerB.view]

http://wiki.jikexueyuan.com/project/objc/images/1-2.png" alt="Inconsistent view hierarchy" />

UIWindow 作為一個應(yīng)用程序的根視圖(root view),是旋轉(zhuǎn)和初始布局消息等事件產(chǎn)生的來源。在上圖中,child view controller 的 view 插入到 root view controller 的視圖層級中,被排除在這些事件之外了。View 事件方法諸如 viewWillAppear: 將不會被調(diào)用。

在 iOS 5 之前構(gòu)建自定義的 view controller 容器時,要保存一個 child view controller 的引用,還要手動在 parent view controller 中轉(zhuǎn)發(fā)所有 view 事件方法的調(diào)用,要做好非常困難。

一個例子

當(dāng)你還是個孩子,在沙灘上玩時,你父母是否告訴過你,如果不停地用鏟子挖,最后會到達(dá)美國?我父母就說過,我就做了個叫做 Tunnel 的 demo 程序來驗證這個說法。你可以 clone 這個 Github 代碼庫并運行這個程序,它有助于讓你更容易理解示例代碼。(劇透:從丹麥西部開始,挖穿地球,你會到達(dá)南太平洋的某個地方)

http://wiki.jikexueyuan.com/project/objc/images/1-3.png" alt="Tunnel screenshot" />

為了尋找對跖點,也稱作相反的坐標(biāo),將拿著鏟子的小孩四處移動,地圖會告訴你對應(yīng)的出口位置在哪里。點擊雷達(dá)按鈕,地圖會翻轉(zhuǎn)過來顯示位置的名稱。

屏幕上有兩個 map view controllers。每個都需要控制地圖的拖動,標(biāo)注和更新。翻過來會顯示兩個新的 view controllers,用來檢索地理位置。所有的 view controllers 都包含于一個 parent view controller 中,它持有它們的 views,并保證正確的布局和旋轉(zhuǎn)行為。

Root view controller 有兩個 container views。添加它們是為了讓布局,以及 child view controllers 的 views 的動畫做起來更容易,我們馬上就可以看到。

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Setup controllers
    _startMapViewController = [RGMapViewController new];
    [_startMapViewController setAnnotationImagePath:@"man"];
    [self addChildViewController:_startMapViewController];          //  1
    [topContainer addSubview:_startMapViewController.view];         //  2
    [_startMapViewController didMoveToParentViewController:self];   //  3
    [_startMapViewController addObserver:self
                              forKeyPath:@"currentLocation"
                                 options:NSKeyValueObservingOptionNew
                                 context:NULL];

    _startGeoViewController = [RGGeoInfoViewController new];        //  4
}

我們實例化了 _startMapViewController,用來顯示起始位置,并設(shè)置了用于標(biāo)注的圖像。

  1. _startMapViewcontroller 被添加成 root view controller 的一個 child。這會自動在 child 上調(diào)用 willMoveToParentViewController: 方法。
  2. child 的 view 被添加成 container view 的 subview。
  3. child 被通知到它現(xiàn)在有一個 parent view controller。
  4. 用來顯示地理位置的 child view controller 被實例化了,但是還沒有被插入到任何 view 或 controller 層級中。

布局

Root view controller 定義了兩個 container views,它決定了 child view controller 的大小。Child view controllers 不知道會被添加到哪個容器中,因此必須適應(yīng)大小。

- (void) loadView
{
    mapView = [MKMapView new];
    mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [mapView setDelegate:self];
    [mapView setMapType:MKMapTypeHybrid];

    self.view = mapView;
}

現(xiàn)在,它們就會用 super view 的 bounds 來進(jìn)行布局。這樣增加了 child view controller 的可復(fù)用性;如果我們把它 push 到 navigation controller 的棧中,它仍然會正確地布局。

過場動畫

Apple 已經(jīng)針對 view controller 容器做了細(xì)致的 API,我們可以構(gòu)造我們能想到的任何容器場景的動畫。Apple 還提供了一個基于 block 的便利方法,來切換屏幕上的兩個 controller views。方法 transitionFromViewController:toViewController:(...) 已經(jīng)為我們考慮了很多細(xì)節(jié)。

- (void) flipFromViewController:(UIViewController*) fromController
               toViewController:(UIViewController*) toController
                  withDirection:(UIViewAnimationOptions) direction
{
    toController.view.frame = fromController.view.bounds;                           //  1
    [self addChildViewController:toController];                                     //
    [fromController willMoveToParentViewController:nil];                            //

    [self transitionFromViewController:fromController
                      toViewController:toController
                              duration:0.2
                               options:direction | UIViewAnimationOptionCurveEaseIn
                            animations:nil
                            completion:^(BOOL finished) {

                                [toController didMoveToParentViewController:self];  //  2
                                [fromController removeFromParentViewController];    //  3
                            }];
}
  1. 在開始動畫之前,我們把 toController 作為一個 child 進(jìn)行添加,并通知 fromController 它將被移除。如果 fromController 的 view 是容器 view 層級的一部分,它的 viewWillDisapear: 方法就會被調(diào)用。
  2. toController 被告知它有一個新的 parent,并且適當(dāng)?shù)?view 事件方法將被調(diào)用。
  3. fromController 被移除了。

這個為 view controller 過場動畫而準(zhǔn)備的便捷方法會自動把老的 view controller 換成新的 view controller。然而,如果你想實現(xiàn)自己的過場動畫,并且希望一次只顯示一個 view,你需要在老的 view 上調(diào)用 removeFromSuperview,并為新的 view 調(diào)用 addSubview:。錯誤的調(diào)用次序通常會導(dǎo)致 UIViewControllerHierarchyInconsistency 警告。例如:在添加 view 之前調(diào)用 didMoveToParentViewController: 就觸發(fā)這個警告。

為了能使用 UIViewAnimationOptionTransitionFlipFromTop 動畫,我們必須把 children's view 添加到我們的 view containers 里面,而不是 root view controller 的 view。否則動畫將導(dǎo)致整個 root view 都翻轉(zhuǎn)。

通信

View controllers 應(yīng)該是可復(fù)用的、自包含的實體。Child view controllers 也不能違背這個經(jīng)驗法則。為了達(dá)到目的,parent view controller 應(yīng)該只關(guān)心兩個任務(wù):布局 child view controller 的 root view,以及與 child view controller 暴露出來的 API 通信。它絕不應(yīng)該去直接修改 child view tree 或其他內(nèi)部狀態(tài)。

Child view controller 應(yīng)該包含管理它們自己的 view 樹的必要邏輯,而不是把它們看作單純呆板的 views。這樣,就有了更清晰的關(guān)注點分離和更好的可復(fù)用性。

在示例程序 Tunnel 中,parent view controller 觀察了 map view controllers 上的一個叫 currentLocation 的屬性。

[_startMapViewController addObserver:self
                          forKeyPath:@"currentLocation"
                             options:NSKeyValueObservingOptionNew
                             context:NULL];

當(dāng)這個屬性跟著拿著鏟子的小孩的移動而改變時,parent view controller 將新坐標(biāo)的對跖點傳遞給另一個地圖:

[oppositeController updateAnnotationLocation:[newLocation antipode]];

類似地,當(dāng)你點擊雷達(dá)按鈕,parent view controller 給新的 child view controllers 設(shè)置待檢索的坐標(biāo)。

[_startGeoViewController setLocation:_startMapViewController.currentLocation];
[_targetGeoViewController setLocation:_targetMapViewController.currentLocation];

我們想要達(dá)到的目標(biāo)和你選擇的手段無關(guān),從 child 到 parent view controller 消息傳遞的技術(shù),不論是采用 KVO,通知,或者是委托模式,child view controller 都應(yīng)該獨立和可復(fù)用。在我們的例子中,我們可以將某個 child view controller 推入到一個 navigation 棧中,它仍然能夠通過相同的 API 進(jìn)行通信。