WWDC 2014 Session筆記 - iOS界面開發(fā)的大一統(tǒng)
本文是我的 WWDC 2014 筆記 中的一篇,涉及的 Session 有
Building Adaptive Apps with UIKit
What's New in Interface Builder
View Controller Advancements in iOS 8
A Look Inside Presentation Controllers
iOS 8 和 OS X 10.10 中一個被強調(diào)了多次的主題就是大一統(tǒng),Apple 希望通過 Hand-off 和各種體驗的無縫切換和集成將用戶黏在由 Apple 設(shè)備構(gòu)成的生態(tài)圈中。而對開發(fā)者而言,今年除了 Swift 的一個大主題也是平臺的統(tǒng)一。在 What's New in Cocoa Touch 的 Seesion 一開始,UIKit 的工程師 Luke 就指出了 iOS 8 SDK 的最重要的關(guān)鍵字就是自適應(yīng) (adaptivity)。這是一個很激動人心的詞,首先自適應(yīng)是一種設(shè)計哲學,盡量使事情保持簡單,我們便可從中擢取優(yōu)雅;另一方面,可能這也是 Apple 不得不做的轉(zhuǎn)變。隨著傳說中的更大屏和超大屏的 iPhone 6 的到來,開發(fā)者在為 iOS 進行開發(fā)的時候似乎也開始面臨著和安卓一樣的設(shè)備尺寸的碎片化的問題。而 iOS 8 所著重希望解決的,就是這一問題。
Size Classes
首先最值得一說的是,iOS 8 應(yīng)用在界面設(shè)計時,迎來了一個可以說是革命性的變化 - Size Classes。
基本概念
在 iPad 和 iPhone 5 出現(xiàn)之前,iOS 設(shè)備就只有一種尺寸。我們在做屏幕適配時需要考慮的僅僅有設(shè)備方向而已。而很多應(yīng)用并不支持轉(zhuǎn)向,這樣的話就完全沒有屏幕適配的工作了。隨著 iPad 和 iPhone 5,以及接下來的 iPhone 6 的推出,屏幕尺寸也變成了需要考慮的對象。在 iOS 7 之前,為一個應(yīng)用,特別是 universal 的應(yīng)用制作 UI 時,我們總會首先想我們的目標設(shè)備的長寬各是多少,方向變換以后布局又應(yīng)該怎么改變,然后進行布局。iOS 6 引入了 Auto Layout 來幫助開發(fā)者使用約束進行布局,這使得在某些情況下我們不再需要考慮尺寸,而可以專注于使用約束來規(guī)定位置。
既然我們有了 Auto Layout,那么其實通過約束來指定視圖的位置和尺寸是沒有什么問題的了,從這個方面來說,屏幕的具體的尺寸和方向已經(jīng)不那么重要了。但是實戰(zhàn)中這還不 夠,Auto Layout 正如其名,只是一個根據(jù)約束來進行布局的方案,而在對應(yīng)不同設(shè)備的具體情況下的體驗上還有欠缺。一個最明顯的問題是它不能根據(jù)設(shè)備類型來確定不同的交互體 驗。很多時候你還是需要判斷設(shè)備到底是 iPhone 還是 iPad,以及現(xiàn)在的設(shè)備方向究竟是豎直還是水平來做出判斷。這樣的話我們還是難以徹底擺脫對于設(shè)備的判斷和依賴,而之后如果有新的尺寸和設(shè)備出現(xiàn)的話, 這種依賴關(guān)系顯然顯得十分脆弱的(想想要是有 iWatch 的話..)。
所以在 iOS 8 里,Apple 從最初的設(shè)計哲學上將原來的方式推翻了,并引入了一整套新的理念,來適應(yīng)設(shè)備不斷的發(fā)展。這就是 Size Classes。
不再根據(jù)設(shè)備屏幕的具體尺寸來進行區(qū)分,而是通過它們的感官表現(xiàn),將其分為普通 (Regular) 和緊密 (Compact) 兩個種類 (class)。開發(fā)者便可以無視具體的尺寸,而是對這這兩類和它們的組合進行適配。這樣不論在設(shè)計時還是代碼上,我們都可以不再受限于具體的尺寸,而是 變成遵循尺寸的視覺感官來進行適配。
簡單來說,現(xiàn)在的 iPad 不論橫屏還是豎屏,兩個方向均是 Regular 的;而對于 iPhone,豎屏時豎直方向為 Regular,水平方向是 Compact,而在橫屏時兩個方向都是 Compact。要注意的是,這里和談到的設(shè)備和方向,都僅僅只是為了給大家一個直觀的印象。相信隨著設(shè)備的變化,這個分類也會發(fā)生變動和更新。Size Classes 的設(shè)計哲學就是尺寸無關(guān),在實際中我們也應(yīng)該盡量把具體的尺寸拋開腦后,而去盡快習慣和適應(yīng)新的體系。
UITraitCollection 和 UITraitEnvironment
為了表征 Size Classes,Apple 在 iOS 8 中引入了一個新的類--UITraitCollection。這個類封裝了像水平和豎直方向的 Size Class 等信息。iOS 8 的 UIKit 中大多數(shù) UI 的基礎(chǔ)類 (包括 UIScreen,UIWindow,UIViewController 和 UIView) 都實現(xiàn)了 UITraitEnvironment 這個接口,通過其中的 traitCollection 這個屬性,我們可以拿到對應(yīng)的 UITraitCollection 對象,從而得知當前的 Size Class,并進一步確定界面的布局。
和 UIKit 中的響應(yīng)者鏈正好相反,traitCollection 將會在 view hierarchy 中自上而下地進行傳遞。對于沒有指定 traitCollection 的 UI 部件,將使用其父節(jié)點的 traitCollection。這在布局包含 childViewController 的界面的時候會相當有用。在 UITraitEnvironment 這個接口中另一個非常有用的是 -traitCollectionDidChange:。在 traitCollection 發(fā)生變化時,這個方法將被調(diào)用。在實際操作時,我們往往會在 ViewController 中重寫 -traitCollectionDidChange: 或者 -willTransitionToTraitCollection:withTransitionCoordinator: 方法 (對于 ViewController 來說的話,后者也許是更好的選擇,因為提供了轉(zhuǎn)場上下文方便進行動畫;但是對于普通的 View 來說就只有前面一個方法了),然后在其中對當前的 traitCollection 進行判斷,并進行重新布局以及動畫。代碼看起來大概會是這個樣子:
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
- withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
- {
- [super willTransitionToTraitCollection:newCollection
- withTransitionCoordinator:coordinator];
- [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
- if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
- //To Do: modify something for compact vertical size
- } else {
- //To Do: modify something for other vertical size
- }
- [self.view setNeedsLayout];
- } completion:nil];
- }
在兩個 To Do 中,我們應(yīng)該刪除或者添加或者更改不同條件下的 Auto Layout 約束 (當然,你也可以干其他任何你想做的事情),然后調(diào)用 -setNeedsLayout 來在上下文中觸發(fā)轉(zhuǎn)移動畫。如果你堅持用代碼來處理的話,可能需要面臨對于不同 Size Classes 來做移除舊的約束和添加新的約束這樣的事情,可以說是很麻煩 (至少我覺得是麻煩的要死)。但是如果我們使用 IB 的話,這些事情和代碼都可以省掉,我們可以非常方便地在 IB 中指定各種 Size Classes 的約束 (稍后會介紹如何使用 IB 來對應(yīng) Size Classes)。另外使用 IB 不僅可以節(jié)約成百上千行的布局代碼,更可以從新的 Xcode 和 IB 中得到很多設(shè)計時就可以實時監(jiān)視,查看并且調(diào)試的特性??梢哉f手寫 UI 和使用 IB 設(shè)計的時間消耗和成本差距被進一步拉大,并且出現(xiàn)了很多手寫 UI 無法實現(xiàn),但是 IB 可以不假思索地完成的任務(wù)。從這個意義上來說,新的 IB 和 Size Classes 系統(tǒng)可以說無情地給手寫代碼判了個死緩。
另外,新的 API 和體系的引入也同時給很多我們熟悉的 UIViewController 的有關(guān)旋轉(zhuǎn)的老朋友判了死刑,比如下面這些 API 都棄用了:
- @property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation
- - willRotateToInterfaceOrientation:duration:
- - willAnimateRotationToInterfaceOrientation:duration:
- - didRotateFromInterfaceOrientation:
- - shouldAutomaticallyForwardRotationMethods
現(xiàn)在全部統(tǒng)一到了 viewWillTransitionToSize:withTransitionCoordinator:,旋轉(zhuǎn)的概念不再被提倡使用。其實仔細想想,所謂旋轉(zhuǎn),不過就是一種 Size 的改變而已,我們都被 Apple 騙了好多年,不是么?
Farewell, I will NOT miss you at all.
在 Interface Builder 中使用 Size Classes
第一次接觸 Xcode 6 和打開 IB 的時候你可能會驚呼,為什么我的畫布變成正方形了。我在第一天 Keynote 結(jié)束后在 Moscone Center 的食堂里第一次打開的時候,還滿以為自己找到了 iWatch 方形顯示屏的確鑿證據(jù)。到后來才知道,這是新的 Size Classes 對應(yīng)的編輯方式。
既然我們不需要關(guān)心實際的具體尺寸,那么我們也就完全沒有必要在 IB 中使用像 3.5/4 寸的 iPhone 或是 10 寸的 iPad 來分開對界面進行編輯。使用一個通用的具有 "代表" 性質(zhì)的尺寸在新體系中確實更不容易使人迷惑。
在現(xiàn)在的 IB 界面的正下方,你可以看到一個 wAny hAny 的按鈕 (因為今年 NDA 的一個明確限制是不能發(fā)相關(guān)軟件截圖,雖然其實可能沒什么太大問題,但是還是尊重 license 比較好),這代表現(xiàn)在的 IB 是對應(yīng)任意高度和任意寬度的。點擊后便可以選擇需要為哪種 Size Class 進行編輯。默認情況在 Any Any 下的修改會對任意設(shè)備和任意方向生效,而如果先進行選擇后再進行編輯,就表示編輯只對選中的設(shè)定生效。這樣我們就很容易在同一個 storyboard 文件里對不同的設(shè)備進行適配:按照設(shè)備需要添加或者編輯某些約束,或者是在特定尺寸下隱藏某些 view (使用 Attribute Inspector 里的 Installed 選框的加號添加)。這使得使用 IB 制作通用程序變簡單了,我們不再需要為 iPhone 和 iPad 準備兩套 storyboard 了。
可以發(fā)揮的想象空間實在太大,一套界面布局通吃所有設(shè)備的畫面太美好,我都不敢想。
Size Classes 和 Image Asset 及 UIAppearence
Image Asset 里也加入了對 Size Classes 的支持,也就是說,我們可以對不同的 Size Class 指定不同的圖片了。在 Image Asset 的編輯面板中選擇某張圖片,Inspector 里現(xiàn)在多了一個 Width 和 Height 的組合,添加我們需要對應(yīng)的 Size Class, 然后把合適的圖拖上去,這樣在運行時 SDK 就將從中挑選對應(yīng)的 Size 的圖進行替換了。不僅如此,在 IB 中我們也可以選擇對應(yīng)的 size 來直接在編輯時查看變化(新的 Xcode 和 IB 添加了非常多編輯時的可視化特性,關(guān)于這方面我有計劃單獨寫一篇可視化開發(fā)的文章進行說明)。
這個特性一個最有用的地方在于對于不同屏幕尺寸可能我們需要的圖像尺寸也有所不同。比如我們希望在 iPhone 豎屏或者 iPad 時的按鈕高一些,而 iPhone 橫屏時由于屏幕高度實在有限,我們希望得到一個扁一些的按鈕。對于純色按鈕我們可以通過簡單的約束和拉伸來實現(xiàn),但是對于有圖案的按鈕,我們之前可能就需 要在 VC 里寫一些臟代碼來處理了?,F(xiàn)在,只需要指定好特定的 Image Asset,然后配置合適的 (比如不含有尺寸限制) 約束,我們就可以一行代碼不寫,就完成這樣復雜的各個機型和方向的適配了。
實際做起來實在是太簡單了..但拿個 demo 說明一下吧,比如下面這個實現(xiàn)了豎直方向 Compact 的時候?qū)⑿δ槗Q成哭臉 -- 當然了,一行代碼都不需要。

另外,在 iOS 7 中 UIImage 添加了一個 renderingMode 屬性。我們可以使用 imageWithRenderingMode: 并傳入一個合適的 UIImageRenderingMode 來指定這個 image 要不要以 Template 的方式進行渲染。在新的 Xcode 中,我們可以直接在 Image Asset 里的 Render As 選項來指定是不是需要作為 template 使用。而相應(yīng)的,在 UIApperance 中,Apple 也為我們對于 Size Classes 添加了相應(yīng)的方法。使用 +appearanceForTraitCollection: 方法,我們就可以針對不同 trait 下的應(yīng)用的 apperance 進行很簡單的設(shè)定。比如在上面的例子中,我們想讓笑臉是綠色,而哭臉是紅色的話,不要太簡單。首先在 Image Asset 里的渲染選項設(shè)置為 Template Image,然后直接在 AppDelegate 里加上這樣兩行:
- UIView.appearanceForTraitCollection(UITraitCollection(verticalSizeClass:.Compact)).tintColor = UIColor.redColor()
- UIView.appearanceForTraitCollection(UITraitCollection(verticalSizeClass:.Regular)).tintColor = UIColor.greenColor()

完成,只不過拖拖鼠標,兩行簡單的代碼,隨后還能隨喜換色,果然是大快所有人心的大好事。
UIViewController 的表現(xiàn)方式
UISplitViewController
在用 Regular 和 Compact 統(tǒng)一了 IB 界面設(shè)計之后,Apple 的工程師可能發(fā)現(xiàn)了一個讓人兩難的歷史問題,這就是 UISplitViewController。一直做 iPhone 而沒太涉及 iPad 的童鞋可能對著這個類不是很熟悉,因為它們是 iPad Only 的。iPad 推出時為了適應(yīng)突然變大的屏幕,并且遠離 "放大版 iTouch" 的詬病,Apple 為 iPad 專門設(shè)計了這個主從關(guān)系的 ViewControlle容器。事實也證明了這個設(shè)計在 iPad 上確實是被廣泛使用,是非常成功的。
現(xiàn)在的問題是,如果我們只有一套 UI 畫布的話,我們要怎么在這個單一的畫布上處理和表現(xiàn)這個 iPad Only 的類呢?
答案是,讓它在 iPhone 上也能用就行了。沒錯,現(xiàn)在你可以直接在 iPhone 上使用 SplitViewController 了。在 Regular 的寬度時,它保持原來的特性,在 DetailViewController 中顯示內(nèi)容,這是毫無疑問的。而在 Compact 中,我們第一想法就是以 push 的表現(xiàn)形式展示。在以前,我們可能需要寫不少代碼來處理這些事情,比如在 AppDelegate 中就在一開始判斷設(shè)備是不是 iPad,然后為應(yīng)用設(shè)定兩套完全不同的導航:一套基于 UINavigationController,另一套基于 UISplitViewController。而現(xiàn)在我們只需要一套 UISplitViewController,并將它的 MasterViewController 設(shè)定為一個 navgationController 就可以輕松搞定所有情況了。
也許你會想,即使這樣,我是不是還是需要判斷設(shè)備是不是 iPad,或者現(xiàn)在的話是判斷 Size Class 是不是 Compact,來決定是要做的到底是 navVC 的 push 還是改變 splitVC 的 viewControllers。其實不用,我們現(xiàn)在可以無痛地不加判斷,直接用統(tǒng)一的方式來完成兩種表現(xiàn)方式。這其中的奧妙在于我們不需要使用 (事實上 iOS 8 后 Apple 也不再提倡使用) UINavigationController 的 pushViewController:animated: 方法了 (又一個老朋友要和我們說再見了)。其實雖然很常用,但是這個方法是一直受到社區(qū)的議論的:因為正是這個方法的存在使得 ViewController 的耦合特性上了一個檔次。在某個 ViewController 中這個方法的存在時,就意味著我們需要確保當前的 ViewController 必須處于一個導航棧的上下文中,這是完全和上下文耦合的一種方式 (雖然我們也可以很蛋疼地用判斷 navController 是不是 nil 來繞開,但是畢竟真的很丑,不是么)。
我們現(xiàn)在有了新的展示 viewController 的方法,-showViewController:sender: 以及 -showDetailViewController:sender:。調(diào)用這兩個方法時,將順著包括調(diào)用 vc 自身的響應(yīng)鏈而上,尋找最近的實現(xiàn)了這個方法的 ViewController 來執(zhí)行相應(yīng)代碼。在 iOS SDK 的默認實現(xiàn)中,在 UISplitViewController 這樣的容器類中,已經(jīng)有這兩個方法的實現(xiàn)方式,而 UINavigationController 也實現(xiàn)了 -showViewController:sender: 的版本。對于在 navController 棧中的 vc,會調(diào)用 push 方式進行展示,而對 splitVC,showViewController:sender: 將在 MasterViewController 中進行 push。而 showDetailViewController:sender: 將根據(jù)水平方向的 Size 的情況進行選擇:對于 Regular 的情況,將在 DetailViewController 中顯示新的 vc,而對于 Compact 的情況,將由所在上下文情況發(fā)回給下級的 navController 或者是直接以 modal 的方式展現(xiàn)。關(guān)于這部分的具體內(nèi)容,可以仔細看看這個示例項目和相關(guān)的文檔 (beta版)。
這么設(shè)計的好處是顯而易見的,首先是解除了原來的耦合,使得我們的 ViewController 可以不被局限于導航控制器上下文中;另外,這幾個方法都是公開的,也就是說我們的 ViewController 可以實現(xiàn)這兩個方法,截斷響應(yīng)鏈的響應(yīng),并實現(xiàn)我們自己的呈現(xiàn)方式。這在自定義 Container Controller 的時候會非常有用。
UIPresentationController
iOS 7 中加入了一套實現(xiàn)非常漂亮的自定義轉(zhuǎn)場動畫的方法 (如果你還不知道或者不記得了,可以看看我去年的這篇筆記)。Apple 在解耦和重用上的努力確實令人驚嘆。而今年,順著自適應(yīng)和平臺開發(fā)統(tǒng)一的東風,在呈現(xiàn) ViewController 的方式上 Apple 也做出了從 iOS SDK 誕生以來最大的改變。iOS 8 中新加入了一個非常重要的類 UIPresentationController,這個 NSObject 的子類將用來管理所有的 ViewController 的呈現(xiàn)。在實現(xiàn)方式上,這個類和去年的自定義轉(zhuǎn)場的幾個類一樣,是完全解耦合的。而 Apple 也在自己的各種 viewController 呈現(xiàn)上完全統(tǒng)一地使用了這個類。
再見 UIPopoverController
和 SplitViewController 類似,UIPopoverController 原來也只是 iPad 使用的,現(xiàn)在 iPhone 上也將適用。準確地說,現(xiàn)在我們不再使用 UIPopoverController 這個類 (雖然現(xiàn)在文檔還沒有將其標為 deprecated,但是估計也是遲早的事兒了),而是改用一個新的類 UIPopoverPresentationController。這是 UIPresentationController 的子類,專門用來負責呈現(xiàn)以 popover 的形式呈現(xiàn)內(nèi)容,是 iOS 8 中用來替代原有的 UIPopoverController 的類。
比起原來的類,新的方式有什么優(yōu)點呢?最大的優(yōu)勢是自適應(yīng),這和 UISplitViewController 在 iOS 8 下的表現(xiàn)是類似的。在 Compact 的寬度條件下,UIPopoverPresentationController 的呈現(xiàn)將會直接變成 modal 出來。這樣我們基本就不再需要去判斷 iPhone 還是 iPad (其實相關(guān)的判定方法也已經(jīng)被標記成棄用了),就可以對應(yīng)不同的設(shè)備了。以前我們可能要寫類似這樣的代碼:
- if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
- let popOverController = UIPopoverController(contentViewController: nextVC)
- popOverController.presentPopoverFromRect(aRect, inView: self.view, permittedArrowDirections: .Any, animated: true)
- } else {
- presentViewController(nextVC, animated: true, completion: nil)
而現(xiàn)在需要做的是:
- nextVC.modalPresentationStyle = .Popover
- let popover = nextVC.popoverPresentationController
- popover.sourceRect = aRect
- popover.permittedArrowDirections = .Any
- presentViewController(nextVC, animated: true, completion: nil)
沒有可惡的條件判斷,一切配置井井有條,可讀性也非常好。
除了自適應(yīng)之外,新方式的另一個優(yōu)點是非常容易自定義。我們可以通過繼承 UIPopoverPresentationController 來實現(xiàn)我們自己想要的呈現(xiàn)方式。其實更準確地說,我們應(yīng)該繼承的是 UIPresentationController,主要通過實現(xiàn) -presentationTransitionWillBegin 和 -presentationTransitionDidEnd: 來自定義我們的展示。像以前我們想要實現(xiàn)只占半個屏幕,后面原來的 view 還可見的 modal,或者是將從下到上的動畫改為百葉窗或者漸隱漸現(xiàn),那都是可費勁兒的事情。而在 UIPresentationController 的幫助下,一切變得十分自然和簡單。在自己的 UIPresentationController 子類中:
- override func presentationTransitionWillBegin() {
- let transitionCoordinator = self.presentingViewController.transitionCoordinator()
- transitionCoordinator.animateAlongsideTransition({context in
- //Do animation here
- }, completion: nil)
- }
- override func presentationTransitionDidEnd(completed: Bool) {
- //Do clean here
- }
具體的用法和 iOS 7 里的自定義轉(zhuǎn)場很類似,設(shè)定需要進行呈現(xiàn)操作的 ViewController 的 transition delegate,在 UIViewControllerTransitioningDelegate 的 -presentationControllerForPresentedViewController:sourceViewController: 方法中使用 -initWithPresentedViewController:presentingViewController: 生成對應(yīng)的 UIPresentationController 子類對象返回給 SDK,然后就可以喝茶看戲了。
再見 UIAlertView, 再見 UIActionSheet
自適應(yīng)和 UIPresentationController 給我們帶來的另一個大變化是 UIAlertView 和 UIActionSheet 這兩個類的消亡 (好吧其實算不上消亡,棄用而已)?,F(xiàn)在,Alert 和 ActionSheet 的呈現(xiàn)也通過 UIPresentationController 來實現(xiàn)。原來在沒有 Size Class 和需要處理旋轉(zhuǎn)的黑暗年代 (抱歉在這里用了這個詞,但是我真的一點也不懷念那段處理設(shè)備旋轉(zhuǎn)的時光) 里,把這兩個 view 顯示出來其實幕后是一堆惡心的事情:創(chuàng)建新的 window,處理新 window 的大小和方向,然后將 alert 或者 action sheet 按合適的大小和方向加到窗口上,然后還要考慮處理轉(zhuǎn)向,最后顯示出來。雖然 Apple 幫我們做了這些事情,但是輪到我們使用時,往往它們也只能滿足最基本的需求。在適配 iPhone 和 iPad 時,UIAlertView 還好,但是對于 UIActionSheet 我們往往又得進行不同處理,來選擇是不是需要 popover。
另外一個要命的地方是因為這兩個類是 iOS 2.0 開始就存在的爺爺級的類了,而最近一直也沒什么大的更新,設(shè)計模式上還使用的是傳統(tǒng)的 delegate 那一套東西。實際上對于這種很輕很明確的使用邏輯,block handler 才是最好的選擇,君不見滿 GitHub 的 block alert view 的代碼,但是沒轍,4.0 才出現(xiàn)的 block 一直由于種種原因,在這兩個類中一直沒有得到官方的認可和使用。
而作為替代品的 UIAlertController 正是為了解決這些問題而出現(xiàn)的,值得注意的是,這是一個 UIViewController 的子類。可能你會問 UIAlertController 對應(yīng)替代 UIAlertView,這很好,但是 UIActionSheet 怎么辦呢?哈..答案是也用 UIAlertController,在 UIAlertController 中有一個 preferredStyle 的屬性,暫時給我們提供了兩種選擇 ActionSheet 和 Alert。在實際使用時,這個類的 API 還是很簡單的,使用工廠方法創(chuàng)建對象,進行配置后直接 present 出來:
- let alert = UIAlertController(title: "Test", message: "Msg", preferredStyle: .Alert)
- let okAction = UIAlertAction(title: "OK", style: .Default) {
- [weak alert] action in
- print("OK Pressed")
- alert!.dismissViewControllerAnimated(true, completion: nil)
- }
- alert.addAction(okAction)
- presentViewController(alert, animated: true, completion: nil)
使用上除了小心循環(huán)引用以外,并沒有太多好說的。在 Alert 上加文本輸入也變得非常簡單了,使用 -addTextFieldWithConfigurationHandler: 每次向其上添加一個文本輸入,然后在 handler 里拿數(shù)據(jù)就好了。
要記住的是,在幕后,做呈現(xiàn)的還是 UIPresentationController。
UISearchDisplayController -> UISearchController
最后想簡單提一下在做搜索欄的時候的同樣類似的改變。在 iOS 8 之前做搜索欄簡直是一件讓人崩潰的事情,而現(xiàn)在我們不再需要討厭的 UISearchDisplayController 了,也沒有莫名其妙的在視圖樹中強制插入 view 了 (如果你做過搜索欄,應(yīng)該知道我在說什么)。這一切在 iOS 8 中也和前面說到的 alert 和 actionSheet 一樣,被一個 UIViewController 的子類 UISearchController 替代了。背后的呈現(xiàn)機制自然也是 UIPresentationController,可見新的這個類在 iOS 8 中的重要性。
總結(jié)
對于廣大 iOS 開發(fā)者賴以生存的 UIKit 來說,這次最大的變化就是 Size Classes 的引入和新的 Presentation 系統(tǒng)了。在 Keynot 上 Craig 就告訴我們,iOS 8 SDK 將是 iOS 開發(fā)誕生以來最大的一次變革,此言不虛。雖然 iOS 8 SDK 的廣泛使用估計還有要有個兩年時間,但是不同設(shè)備的開發(fā)的 API 的統(tǒng)一這一步已然邁出,這也正是 Apple 之后的發(fā)展方向。正如兩年前的 Auto Layout 正在今天大放光彩一樣,之后 Size Classes 和新的 ViewController 也必將成為日常開發(fā)的主力工具。
程序員嘛,果然需要每年不斷學習,才能跟上時代。
本文鏈接:http://www.cocoachina.com/applenews/devnews/2014/0729/9269.html
【責任編輯:chenqingxiang TEL:(010)68476606】


































