在屏幕上顯示視圖控制器有兩種方法:嵌入到容器視圖控制器中或者present這個視圖控制器伴澄。容器視圖控制器提供應(yīng)用的主要導(dǎo)航考余,但present視圖控制器同樣也是一個重要的導(dǎo)航工具菲茬。可以在當(dāng)前的視圖控制器上直接present一個新的視圖控制器愕秫。通常承疲,當(dāng)你希望實(shí)現(xiàn)modal界面時,可以present視圖控制器冲呢,但你也可以使用它們用于其他用途舍败。
UIViewController 類支持present視圖控制器,可用于所有的視圖控制器對象敬拓。你可以在任何其他視圖控制器上present任何一個視圖控制器邻薯,雖然UIKit可能重新路由該請求到不同的視圖控制器上。present視圖控制器會在原始視圖控制器之間創(chuàng)建關(guān)系乘凸,原始視圖控制器稱為 presenting view controller厕诡,顯示的新視圖控制器稱為presented view controller。這個關(guān)系是視圖控制器層級結(jié)構(gòu)的一部分营勤,直到presented視圖控制器被dismiss木人。
展示和過渡的過程
present一個視圖控制器是一種快速而簡單的方法在屏幕上推出新內(nèi)容信柿。UIKit內(nèi)置present機(jī)制冀偶,允許使用內(nèi)置或自定義動畫來顯示一個新的視圖控制器醒第。內(nèi)置present和動畫需要很少的代碼因?yàn)閁IKit處理了所有的工作。你也可以很容易的在任何視圖控制器創(chuàng)建自定義present和動畫进鸠。
你可以以編程方式或使用segue來發(fā)起視圖控制器的present稠曼。如果在設(shè)計(jì)時你知道應(yīng)用的導(dǎo)航,segue是發(fā)起present最簡單的方式客年。更多動態(tài)界面霞幅,或者沒有專門的控件發(fā)起segue的情況下,使用 UIViewController方法來present視圖控制器量瓜。
Presentation Styles
presentation style 是一個視圖控制器管理其屏幕上的外觀司恳。UIKit定義了許多標(biāo)準(zhǔn)的present風(fēng)格,每個都有特定的外觀和意圖绍傲。你也可以定義自定義present風(fēng)格扔傅。當(dāng)設(shè)計(jì)你的應(yīng)用時,為你的應(yīng)用選擇合適的present風(fēng)格烫饼,并為要present的視圖控制器的 modalPresentationStyle屬性分配適合的常數(shù)猎塞。
Full-Screen Presentation Styles
Full screen presentation styles覆蓋全部屏幕,防止與底層內(nèi)容互動杠纵。在水平常規(guī)環(huán)境中荠耽,只有full-screen styles完全覆蓋了底層內(nèi)容。其余變暗或有透明度的視圖允許部分底層視圖控制器顯示比藻。在水平緊湊環(huán)境中铝量,full-screen present方式自動采用UIModalPresentationFullScreen
風(fēng)格并覆蓋所有底層內(nèi)容。
圖8-1 說明在水平常規(guī)環(huán)境使用UIModalPresentationFullScreen,UIModalPresentationPageSheet和UIModalPresentationFormSheet風(fēng)格present方式的外觀银亲。在圖中慢叨,在左上角的綠色視圖控制器present在右上角的藍(lán)色視圖控制器,各種present風(fēng)格如下群凶。對于一些present風(fēng)格插爹,UIKit在兩個視圖控制器內(nèi)容之間插入一個半透明視圖。
注意
當(dāng)使用
UIModalPresentationFullScreen
風(fēng)格present一個視圖控制器時请梢,UIKit通常在完成過渡動畫后刪除底層視圖控制器的視圖赠尾。你可以通過指定UIModalPresentationOverFullScreen風(fēng)格防止刪除這些視圖。當(dāng)present的視圖控制器有透明區(qū)域讓底層內(nèi)容顯示時可以采用這種風(fēng)格毅弧。
當(dāng)使用一種present 風(fēng)格時气嫁,視圖控制器啟動的present必須覆蓋整個屏幕。如果將要present的視圖控制器不能覆蓋整個屏幕够坐,UIKit遍歷視圖控制器層級直到找到一個覆蓋整個屏幕的視圖控制器寸宵。如果不能找到一個中間視圖控制器充滿屏幕崖面,UIKit使用窗口的根視圖控制器。
The Popover Style
UIModalPresentationPopover風(fēng)格以彈出窗口的方式顯示在視圖控制器上梯影。popover用于顯示額外信息或項(xiàng)目列表中選中的對象巫员。在橫向常規(guī)環(huán)境中,popover視圖僅覆蓋屏幕的一部分甲棍,如圖8-2所示简识。在橫向緊湊環(huán)境中,popover默認(rèn)采用UIModalPresentationOverFullScreen present方式感猛。在popover視圖外點(diǎn)擊七扰, popover視圖將自動dismiss。
因?yàn)樵谒骄o湊環(huán)境中陪白,popover采用full-screen 的present方式颈走,通常需要修改popover代碼處理適配。在full-screen模式咱士,需要一種方法dismiss掉present的popover立由。你可以通過添加一個按鈕,將popover嵌入到將要dismiss的容器視圖控制器司致,或者改變自適應(yīng)行為本身拆吆。
如何配置彈窗,參見在視圖控制器上present彈窗( Presenting a View Controller in a Popover)脂矫。
The Current Context Styles
UIModalPresentationCurrentContext 風(fēng)格在界面覆蓋了一個特殊的視圖控制器枣耀。當(dāng)使用contextual風(fēng)格,通過設(shè)置 definesPresentationContext屬性為YES庭再,指定要覆蓋的視圖控制器捞奕。圖8-3說明了current context 只覆蓋分屏視圖控制器的一個子視圖控制器。
注意
當(dāng)使用
UIModalPresentationFullScreen
風(fēng)格present一個視圖控制器拄轻,UIKit通常在過渡動畫完成后刪除底層視圖控制器的視圖颅围。可以設(shè)置UIModalPresentationOverCurrentContext風(fēng)格恨搓,防止刪除那些視圖院促。當(dāng)present的視圖控制器有透明區(qū)域讓底層內(nèi)容顯示時,可以使用該風(fēng)格斧抱。
定義視圖控制器還可以在present過程中定義過渡動畫常拓。通常,當(dāng)使用present視圖控制器的 modalTransitionStyle屬性辉浦,UIKit渲染視圖控制器到屏幕弄抬。如果present context視圖控制器的 providesPresentationContextTransitionStyle值設(shè)為YES,UIKit使用視圖控制器的modalTransitionStyle
屬性代替宪郊。
當(dāng)過渡到水平緊湊的環(huán)境掂恕,current context風(fēng)格采用 UIModalPresentationFullScreen 風(fēng)格拖陆。為了改變該行為,使用自適應(yīng)present委托指定不同的present風(fēng)格或視圖控制器懊亡。
Custom Presentation Styles
UIModalPresentationCustom風(fēng)格使用自定義的風(fēng)格present視圖控制器依啰。創(chuàng)建一個自定義風(fēng)格包括子類化UIPresentationController ,使用其方法來渲染任何自定義視圖到屏幕上并設(shè)置present視圖控制器的大小和位置斋配。present控制器還處理由于視圖控制器的trait變化引起的適配孔飒。
如何定義自定義present視圖控制器的信息,參見創(chuàng)建自定義present( Creating Custom Presentations)艰争。
Transition Styles
Transition風(fēng)格決定用于顯示present視圖控制器的動畫類型。對于內(nèi)置transition風(fēng)格桂对,你可以為present視圖控制器的 modalTransitionStyle屬性指定一種標(biāo)準(zhǔn)transition風(fēng)格甩卓。當(dāng)present視圖控制器,UIKit創(chuàng)建相應(yīng)的動畫風(fēng)格蕉斜。例如逾柿,圖8-4說明了標(biāo)準(zhǔn)slide-up過渡(UIModalTransitionStyleCoverVertical)如何視圖控制器渲染到屏幕上。視圖控制器B開始在屏幕外宅此,并覆蓋到視圖控制器A上机错。當(dāng)dismiss視圖控制器B,動畫逆轉(zhuǎn)父腕,B下滑露出A弱匪。
可以使用動畫對象和過渡代理來創(chuàng)建自定義過渡。動畫對象為屏幕上放置的視圖控制器創(chuàng)建過渡動畫璧亮。過渡代理在合適的時間為UIKit提供動畫對象萧诫。更多關(guān)于如何實(shí)現(xiàn)自定義過渡的信息,參見自定義過渡動畫(Customizing the Transition Animations)枝嘶。
present和顯示一個視圖控制器
UIViewController類提供兩種方法來顯示一個視圖控制器:
- showViewController:sender:和 showDetailViewController:sender:方法為顯示視圖控制器提供最大限度的適應(yīng)性和靈活性帘饶。這些方法讓present視圖控制器決定如何最好的處理present。例如群扶,容器視圖控制器可能合并視圖控制器作為子視圖控制器而不是以模態(tài)的方式present及刻。默認(rèn)以模態(tài)的方式present視圖控制器。
- presentViewController:animated:completion: 方法總是以模態(tài)的方式顯示視圖控制器竞阐。視圖控制器調(diào)用這個方法可能不會最終處理present但總是以模態(tài)的方式present缴饭。在水平緊湊環(huán)境中,該方法采用該present風(fēng)格馁菜。
showViewController:sender:
和showDetailViewController:sender:
方法是啟動present的首選方法茴扁。視圖控制器可以調(diào)用它們,而不用知道任何關(guān)于視圖控制器層級結(jié)構(gòu)或當(dāng)前視圖控制器在層級結(jié)構(gòu)的位置汪疮。這些方法使重用視圖控制器更加容易峭火,而無需編寫條件代碼路徑毁习。
present視圖控制器
有幾種方法可以present視圖控制器:
- 使用segue自動present視圖控制器。使用界面構(gòu)建器指定的信息卖丸,segue實(shí)例化并present視圖控制器纺且。關(guān)于如何配置segue的更多信息,參見使用segue( Using Segues)稍浆。
- 使用 showViewController:sender: 和 showDetailViewController:sender:方法顯示視圖控制器载碌。在自定義視圖控制器中,可以改變這些方法的行為使之更加適合你的視圖控制器衅枫。
- 調(diào)用presentViewController:animated:completion:方法以模態(tài)的方式present視圖控制器嫁艇。
關(guān)于如何dismiss使用這些技術(shù)present的視圖控制的更多信息,參見dismiss一個presented的視圖控制器( Dismissing a Presented View Controller)弦撩。
顯示視圖控制器
當(dāng)使用和方法步咪,得到屏幕上一個新的視圖控制器的過程很簡單:
- 創(chuàng)建你希望present的視圖控制器對象。當(dāng)創(chuàng)建視圖控制器時益楼,你負(fù)責(zé)初始化它執(zhí)行任何所需的任何數(shù)據(jù)猾漫。
- 設(shè)置新視圖控制器的 modalPresentationStyle屬性是首選present風(fēng)格。該風(fēng)格可能不用于最終的present感凤。
- 設(shè)置視圖控制器的modalTransitionStyle屬性設(shè)置所需的過渡動畫風(fēng)格悯周。該風(fēng)格可能不用于最終的present。
- 調(diào)用當(dāng)前視圖控制器的 showViewController:sender:和showDetailViewController:sender:方法陪竿。
UIKit轉(zhuǎn)發(fā)showViewController:sender:
和showDetailViewController:sender:
方法的調(diào)用給present視圖控制器禽翼。視圖控制器可以決定如何最好的執(zhí)行present,并且可以根據(jù)需呀改變present和過渡風(fēng)格萨惑。例如捐康,導(dǎo)航控制器可能push該視圖控制器到導(dǎo)航堆棧。
關(guān)于顯示視圖控制器和以模態(tài)的方式present視圖控制器的差異信息庸蔼,參見present和顯示視圖控制器( Presenting Versus Showing a View Controller)解总。
以模態(tài)的方式present視圖控制器
當(dāng)直接present視圖控制器,你需要告訴UIKit你希望視圖控制器如何顯示以及如何渲染到屏幕上姐仅。
創(chuàng)建你希望present的視圖控制器對象花枫。當(dāng)創(chuàng)建視圖控制器時,你負(fù)責(zé)初始化它執(zhí)行任何所需的任何數(shù)據(jù)掏膏。
- 設(shè)置新視圖控制器的 modalPresentationStyle 屬性為所需的present風(fēng)格劳翰。
- 設(shè)置視圖控制器的 modalTransitionStyle屬性為所需的動畫風(fēng)格。
- 調(diào)用當(dāng)前視圖控制器的 presentViewController:animated:completion:方法馒疹。
調(diào)用presentViewController:animated:completion:
方法的視圖控制器可能不是最終執(zhí)行模態(tài)present的視圖控制器佳簸。present風(fēng)格決定了視圖控制器如何被present,包括present視圖控制器所需的特征。例如生均,一個全屏present必須由一個全屏視圖控制器啟動听想。如果當(dāng)前present視圖控制器不合適,UIKit遍歷視圖控制器層級直到找到合適的马胧。完成模態(tài)present后汉买,UIKit更新受影響的視圖控制器的presentingViewController和 presentedViewController屬性。
列表8-1 演示了如何以編程的方式present一個視圖控制器佩脊。當(dāng)用戶添加一個新視圖控制器蛙粘,應(yīng)用提示用戶輸入present導(dǎo)航視圖控制器的基本信息。被選中的導(dǎo)航控制器會在標(biāo)準(zhǔn)的地方放置一個取消和完成按鈕威彰。使用導(dǎo)航控制器使擴(kuò)展新界面更加容易出牧。你所需要做的是push新視圖控制器到導(dǎo)航堆棧。
列表8-1 以編程的方式present一個視圖控制器
<pre><code>
- (void)add:(id)sender {
- // Create the root view controller for the navigation controller
- // The new view controller configures a Cancel and Done button for the
- // navigation bar.
- RecipeAddViewController *addController = [[RecipeAddViewController alloc] init];
- addController.modalPresentationStyle = UIModalPresentationFullScreen;
- addController.transitionStyle = UIModalTransitionStyleCoverVertical;
- [self presentViewController:addController animated:YES completion: nil];
- }
</pre></code>
以彈窗形式present視圖控制器
在present視圖控制器之前抱冷,popover需要額外的配置崔列。在設(shè)置模態(tài)present風(fēng)格為 UIModalPresentationPopover后,配置一下popover相關(guān)屬性:
- 設(shè)置視圖控制器的 preferredContentSize屬性為所需的大小旺遮。
- 使用相關(guān)UIPopoverPresentationController對象設(shè)置popover錨點(diǎn),該對象可用于視圖控制器的 popoverPresentationController屬性盈咳。設(shè)置一下其中一種:
- -設(shè)置屬性為bar button耿眉。
- -設(shè)置 sourceView 和 sourceRect屬性指定特定視圖區(qū)域。
可以使用 UIPopoverPresentationController對象在需要時調(diào)整彈窗的外觀鱼响。彈窗present控制器還支持代理對象鸣剪,可以使用它來響應(yīng)在present過程中的變化。例如丈积,你可以使用代理來響應(yīng)彈窗在屏幕上出現(xiàn)筐骇、消失或重新定位。關(guān)于該對象的更多信息江滨,參見UIPopoverPresentationController類引用(UIPopoverPresentationController Class Reference)铛纬。
dismiss一個presented的視圖控制器
調(diào)用presenting視圖控制器的dismissViewControllerAnimated:completion:方法來dismiss一個presented的視圖控制器。你可以在presented視圖控制器本身的方法唬滑。當(dāng)presented視圖控制器調(diào)用該方法告唆,UIKit自動轉(zhuǎn)發(fā)請求到presenting視圖控制器。
在dismiss視圖控制器前保存任何重要信息晶密。dismiss視圖控制器會將其從視圖控制器層級結(jié)構(gòu)刪除并從屏幕上刪除視圖擒悬。如果在其他地方存儲的視圖控制器沒有強(qiáng)引用,dismiss該視圖控制器會釋放與之關(guān)聯(lián)的內(nèi)存稻艰。
如果presented視圖控制器必須返回?cái)?shù)據(jù)到presenting視圖控制器懂牧,使用 delegation 設(shè)計(jì)模式來完成傳遞。代理使應(yīng)用視圖控制器的重用更容易尊勿。使用代理僧凤,presented視圖控制器存儲代理對象的引用畜侦,實(shí)現(xiàn)正式protocol的方法。Presented視圖控制器在代理調(diào)用這些方法用于收集結(jié)果拼弃。在典型的實(shí)現(xiàn)中夏伊,presenting視圖控制器作為presented視圖控制器的代理。
present在不同storyboard種定義的視圖控制器
雖然在同一storyboard中的兩個視圖控制器之間可以創(chuàng)建segue吻氧,但在不同storyboard中不能創(chuàng)建segue溺忧。當(dāng)你希望顯示存儲在另一個storyboard中的視圖控制器時,你必須在present之前顯式的實(shí)例化該視圖控制器盯孙,如列表8-2所示鲁森。例子以模態(tài)的方式present視圖控制器,但你可以push它到導(dǎo)航控制器或以其他方式顯示振惰。
列表8-2 加載storyboard中的視圖控制器
<pre><code>
- UIStoryboard* sb = [UIStoryboard storyboardWithName:@"SecondStoryboard" bundle:nil];
- MyViewController* myVC = [sb instantiateViewControllerWithIdentifier:@"MyViewController"];
- // Configure the view controller.
- // Display the view controller
- [self presentViewController:myVC animated:YES completion:nil];
</pre></code>
沒有要求你必須在應(yīng)用中創(chuàng)建多個storyboard歌溉。不過,在這里有一些情況下多個storyboard可能有用:
- 你有一個大的編程團(tuán)隊(duì)骑晶,不同的用戶界面分配給團(tuán)隊(duì)的不同部分痛垛。每個團(tuán)隊(duì)擁有不同的storyboard文件以減少沖突。
- 你購買或創(chuàng)建一個庫預(yù)定義了視圖控制器類型集合桶蛔;這些視圖控制器的內(nèi)容定義在庫中的storyboard中匙头。
- 你有需要在屏幕外顯示的內(nèi)容。在這種情況下仔雷,你可能保持所有視圖控制器與單獨(dú)storyboard的視圖控制器相關(guān)蹂析。相同場景的另一種模式是編寫一個自定義segue。