有兩種方法在屏幕上顯示視圖控制器:將其嵌入到容器視圖控制器中或呈現(xiàn)它。 容器視圖控制器提供應(yīng)用程序的主導(dǎo)航兔辅,但是呈現(xiàn)視圖控制器也是一個(gè)重要的導(dǎo)航工具肤频。 您使用直接演示在當(dāng)前視圖控制器的頂部顯示新的視圖控制器粪摘。 通常瀑晒,當(dāng)您想要實(shí)現(xiàn)模態(tài)界面時(shí),您可以使用呈現(xiàn)視圖控制器徘意,但是您也可以將它們用于其他用途苔悦。
支持呈現(xiàn)視圖控制器內(nèi)置在UIViewController類中,并且可用于所有視圖控制器對(duì)象椎咧。 您可以呈現(xiàn)來自任何其他視圖控制器的任何視圖控制器玖详,雖然UIKit可能會(huì)將請(qǐng)求重新路由到不同的視圖控制器。 呈現(xiàn)視圖控制器創(chuàng)建被稱為呈現(xiàn)視圖控制器的原始視圖控制器和被顯示的新視圖控制器之間的關(guān)系,被稱為呈現(xiàn)的視圖控制器蟋座。 此關(guān)系形成視圖控制器層次結(jié)構(gòu)的一部分拗踢,并且保持就位,直到呈現(xiàn)的視圖控制器被解除向臀。
展示與過渡過程
呈現(xiàn)視圖控制器是一種快速和簡單的方式來將新內(nèi)容設(shè)置到屏幕上巢墅。 UIKit中內(nèi)置的演示機(jī)制允許您使用內(nèi)置或自定義動(dòng)畫顯示新的視圖控制器。 內(nèi)置的展示和動(dòng)畫需要很少的代碼飒硅,因?yàn)閁IKit處理所有的工作砂缩。 您也可以創(chuàng)建自定義展示和動(dòng)畫作谚,而不需要額外的工作三娩,并與任何視圖控制器使用它們。
您可以以編程方式或使用segues啟動(dòng)視圖控制器的呈現(xiàn)妹懒。 如果你在設(shè)計(jì)時(shí)知道你的應(yīng)用程序的導(dǎo)航雀监,segues是最簡單的方式來啟動(dòng)界面。 對(duì)于更多動(dòng)態(tài)界面眨唬,或在沒有專門控制來啟動(dòng)segue的情況下会前,使用UIViewController的方法來呈現(xiàn)視圖控制器。
呈現(xiàn)方式
視圖控制器的呈現(xiàn)方式控制其在屏幕上的外觀匾竿。 UIKit定義了許多標(biāo)準(zhǔn)的呈現(xiàn)方式瓦宜,每個(gè)都有一個(gè)特定的外觀和意圖。 您還可以定義自己的自定義呈現(xiàn)方式岭妖。 在設(shè)計(jì)應(yīng)用程序時(shí)临庇,選擇最適合您想要做的操作的呈現(xiàn)方式,并將適當(dāng)?shù)臅r(shí)候分配給要呈現(xiàn)的視圖控制器的modalPresentationStyle屬性昵慌。
全屏呈現(xiàn)方式
全屏呈現(xiàn)方式覆蓋整個(gè)屏幕假夺,防止與底層內(nèi)容的交互。 在水平常規(guī)環(huán)境中斋攀,只有一個(gè)全屏方式完全覆蓋基礎(chǔ)內(nèi)容已卷。 其余包含調(diào)光視圖或透明度,以允許下層視圖控制器的部分顯示淳蔼。 在水平緊湊的環(huán)境中侧蘸,全屏演示自動(dòng)適應(yīng)UIModalPresentationFullScreen方式并涵蓋所有底層內(nèi)容。
圖8-1說明使用uimodalpresentationfullscreen鹉梨,uimodalpresentationpagesheet呈現(xiàn)方式的外觀讳癌,并在水平正常的環(huán)境uimodalpresentationformsheet風(fēng)格。在圖中俯画,頂部左側(cè)的綠色視圖控制器呈現(xiàn)頂部右側(cè)的藍(lán)色視圖控制器析桥,每個(gè)顯示樣式的結(jié)果如下所示。對(duì)于一些呈現(xiàn)方式,UIKit插入一個(gè)調(diào)光的視圖的兩個(gè)視圖控制器的內(nèi)容泡仗。
圖8-1全屏呈現(xiàn)方式
注意
當(dāng)使用UIModalPresentationFullScreen方式呈現(xiàn)視圖控制器時(shí)埋虹,UIKit通常在
轉(zhuǎn)換動(dòng)畫完成后刪除基礎(chǔ)視圖控制器的視圖。 您可以通過指定
UIModalPresentationOverFullScreen樣式來防止刪除這些視圖娩怎。 當(dāng)呈現(xiàn)的視
圖控制器具有允許基礎(chǔ)內(nèi)容顯示的透明區(qū)域時(shí)搔课,您可以使用該樣式。
當(dāng)使用全屏呈現(xiàn)方式之一時(shí)截亦,發(fā)起呈現(xiàn)的視圖控制器必須自己覆蓋整個(gè)屏幕爬泥。 如果呈現(xiàn)視圖控制器不覆蓋屏幕,UIKit會(huì)在視圖控制器層次結(jié)構(gòu)上查找覆蓋全屏的崩瓤,直到它找到一個(gè)袍啡。 如果它找不到填充屏幕的中間視圖控制器,UIKit使用窗口的根視圖控制器却桶。
彈出方式
UIModalPresentationPopover方式在彈出視圖中顯示視圖控制器境输。 彈出式窗口可用于顯示附加信息或與關(guān)注或選定對(duì)象相關(guān)的項(xiàng)目列表。 在水平常規(guī)環(huán)境中颖系,彈出視圖僅覆蓋屏幕的一部分嗅剖,如圖8-2所示。 在水平緊湊的環(huán)境中嘁扼,默認(rèn)情況下信粮,popovers適應(yīng)UIModalPresentationOverFullScreen表示方式。 在popover視圖之外輕擊會(huì)自動(dòng)關(guān)閉popover趁啸。
圖8-2 彈出呈現(xiàn)方式
因?yàn)閺棾龇绞竭m合在水平緊湊的環(huán)境中的全屏顯示强缘,所以通常需要修改彈出方式代碼來處理適配。 在全屏模式下莲绰,您需要一種方法來關(guān)閉所顯示的popover欺旧。 你可以通過添加一個(gè)按鈕,將popover嵌入一個(gè)可忽略的容器視圖控制器蛤签,或者改變自適應(yīng)行為本身辞友。
當(dāng)前上下文方式
UIModalPresentationCurrentContext樣式涵蓋了接口中的特定視圖控制器。 當(dāng)使用上下文方式時(shí)震肮,通過將其definitionsPresentationContext屬性設(shè)置為YES來指定要覆蓋哪個(gè)視圖控制器称龙。 圖8-3示出了僅覆蓋拆分視圖控制器的一個(gè)子視圖控制器的當(dāng)前上下文表示。
圖8-3 當(dāng)前上下文呈現(xiàn)方式
注意
當(dāng)使用UIModalPresentationFullScreen方式呈現(xiàn)視圖控制器時(shí)戳晌,UIKit通常在
轉(zhuǎn)換動(dòng)畫完成后刪除基礎(chǔ)視圖控制器的視圖鲫尊。 您可以通過指定
UIModalPresentationOverCurrentContext樣式來防止刪除這些視圖。 當(dāng)呈現(xiàn)
的視圖控制器具有允許基礎(chǔ)內(nèi)容顯示的透明區(qū)域時(shí)沦偎,您可以使用該方式疫向。
定義呈現(xiàn)上下文的視圖控制器還可以定義在呈現(xiàn)期間使用的轉(zhuǎn)換動(dòng)畫咳蔚。 通常,UIKit使用呈現(xiàn)的視圖控制器的modalTransitionStyle屬性中的值在屏幕上動(dòng)畫顯示控制器搔驼。 如果演示文稿上下文視圖控制器的providesPresentationContextTransitionStyle設(shè)置為YES谈火,UIKit將使用該視圖控制器的modalTransitionStyle屬性中的值。
當(dāng)轉(zhuǎn)換到水平緊湊環(huán)境時(shí)舌涨,當(dāng)前上下文樣式適應(yīng)UIModalPresentationFullScreen樣式糯耍。 要更改此行為,請(qǐng)使用自適應(yīng)呈現(xiàn)委派來指定不同的呈現(xiàn)樣式或視圖控制器囊嘉。
自定義呈現(xiàn)方式
UIModalPresentationCustom方式允許你使用定義的自定義方式來呈現(xiàn)視圖控制器温技。 創(chuàng)建自定義方式涉及對(duì)UIPresentationController子類化,并使用其方法將任何自定義視圖動(dòng)畫化到屏幕上扭粱,并設(shè)置呈現(xiàn)的視圖控制器的大小和位置舵鳞。 呈現(xiàn)控制器還處理由于呈現(xiàn)的視圖控制器的特性的改變而發(fā)生的任何適配。
過渡方式
過渡方式確定用于顯示所呈現(xiàn)的視圖控制器的動(dòng)畫類型焊刹。 對(duì)于內(nèi)置的轉(zhuǎn)換方式系任,可以將一個(gè)標(biāo)準(zhǔn)轉(zhuǎn)換方式分配給要顯示的視圖控制器的modalTransitionStyle屬性恳蹲。 當(dāng)您呈現(xiàn)視圖控制器時(shí)虐块,UIKit將創(chuàng)建與該樣式對(duì)應(yīng)的動(dòng)畫。 例如嘉蕾,圖8-4說明了標(biāo)準(zhǔn)上滑過渡(UIModalTransitionStyleCoverVertical)如何在屏幕上動(dòng)畫視圖控制器贺奠。 視圖控制器B從屏幕開始并且向上和向上移動(dòng)視圖控制器A的頂部。當(dāng)視圖控制器B被關(guān)閉時(shí)错忱,動(dòng)畫反轉(zhuǎn)儡率,使得B向下滑動(dòng)以顯示A.
圖8-4視圖控制器的過渡動(dòng)畫
您可以使用animator對(duì)象和轉(zhuǎn)換委托創(chuàng)建自定義轉(zhuǎn)場(chǎng)。 動(dòng)畫制作器對(duì)象創(chuàng)建用于將視圖控制器放置在屏幕上的過渡動(dòng)畫以清。 轉(zhuǎn)換委托在適當(dāng)?shù)臅r(shí)間將動(dòng)畫對(duì)象提供給UIKit儿普。
呈現(xiàn)或顯示視圖控制器
UIViewController類提供了兩種顯示視圖控制器的方法:
- showViewController:sender:和showDetailViewController:sender:方法提供了最適應(yīng)和靈活的方式來顯示視圖控制器。 這些方法讓呈現(xiàn)視圖控制器決定如何最好地處理呈現(xiàn)掷倔。 例如眉孩,容器視圖控制器可以將視圖控制器合并為子控制器,而不是模態(tài)地呈現(xiàn)它勒葱。 默認(rèn)行為以模態(tài)方式呈現(xiàn)視圖控制器浪汪。
- presentViewController:animated:completion:方法總是以模態(tài)方式顯示視圖控制器。 調(diào)用此方法的視圖控制器可能不會(huì)最終處理呈現(xiàn)凛虽,但呈現(xiàn)總是模態(tài)死遭。 此方法適應(yīng)水平緊湊環(huán)境的呈現(xiàn)風(fēng)格。
showViewController:sender:和showDetailViewController:sender:方法是啟動(dòng)呈現(xiàn)視圖的首選方法凯旋。 視圖控制器可以在不知道關(guān)于視圖控制器層次結(jié)構(gòu)的其余部分或當(dāng)前視圖控制器在該層次結(jié)構(gòu)中的位置的任何情況下調(diào)用它們呀潭。 這些方法還使得更容易在應(yīng)用程序的不同部分重用視圖控制器钉迷,而無需編寫條件代碼路徑。
呈現(xiàn)視圖控制器
有幾種方式來啟動(dòng)視圖控制器的呈現(xiàn):
- 使用segue自動(dòng)呈現(xiàn)視圖控制器钠署。 segue使用您在Interface Builder中指定的信息實(shí)例化并呈現(xiàn)視圖控制器篷牌。
- 使用showViewController:sender:或showDetailViewController:sender:方法來顯示視圖控制器。 在自定義視圖控制器中踏幻,您可以將這些方法的行為更改為更適合于視圖控制器的行為枷颊。
- 調(diào)用presentViewController:animated:completion:方法以模態(tài)方式呈現(xiàn)視圖控制器。
顯示視圖控制器
當(dāng)使用showViewController:sender:和showDetailViewController:sender:方法時(shí)该面,在屏幕上獲取新的視圖控制器的過程是直接的:
- 創(chuàng)建要顯示的視圖控制器對(duì)象夭苗。 在創(chuàng)建視圖控制器時(shí),您有責(zé)任使用執(zhí)行其任務(wù)所需的任何數(shù)據(jù)對(duì)其進(jìn)行初始化隔缀。
- 將新視圖控制器的modalPresentationStyle屬性設(shè)置為首選顯示方式题造。 此方式可能不會(huì)在最終呈現(xiàn)中使用。
- 將視圖控制器的modalTransitionStyle屬性設(shè)置為所需的過渡動(dòng)畫方式猾瘸。 此方式可能不會(huì)在最終的動(dòng)畫中使用界赔。
- 調(diào)用當(dāng)前視圖控制器的showViewController:sender:和showDetailViewController:sender:方法。
UIKit將對(duì)showViewController:sender:和showDetailViewController:sender:方法的調(diào)用轉(zhuǎn)發(fā)到相應(yīng)的呈現(xiàn)視圖控制器牵触。 然后淮悼,視圖控制器可以決定如何最好地執(zhí)行呈現(xiàn),并且可以根據(jù)需要改變呈現(xiàn)和轉(zhuǎn)換樣式揽思。 例如袜腥,導(dǎo)航控制器可以將視圖控制器推到其導(dǎo)航堆棧上。
模式地呈現(xiàn)視圖控制器
當(dāng)直接呈現(xiàn)視圖控制器時(shí)钉汗,您可以告訴UIKit如何顯示新的視圖控制器以及如何在屏幕上動(dòng)畫羹令。
- 創(chuàng)建要顯示的視圖控制器對(duì)象。
在創(chuàng)建視圖控制器時(shí)损痰,您有責(zé)任使用執(zhí)行其任務(wù)所需的任何數(shù)據(jù)對(duì)其進(jìn)行初始化福侈。 - 將新視圖控制器的modalPresentationStyle屬性設(shè)置為所需的顯示樣式。
- 將視圖控制器的modalTransitionStyle屬性設(shè)置為所需的動(dòng)畫樣式卢未。
- 調(diào)用當(dāng)前視圖控制器的presentViewController:animated:completion:方法肪凛。
調(diào)用presentViewController:animated:completion:方法的視圖控制器可能不是實(shí)際執(zhí)行模態(tài)呈現(xiàn)的視圖控制器。 呈現(xiàn)風(fēng)格確定如何呈現(xiàn)視圖控制器尝丐,包括呈現(xiàn)視圖控制器所需的特性显拜。 例如,全屏顯示必須由全屏視圖控制器啟動(dòng)爹袁。 如果當(dāng)前呈現(xiàn)視圖控制器不合適远荠,UIKit會(huì)遍歷視圖控制器層次結(jié)構(gòu),直到它找到一個(gè)失息。 完成模態(tài)顯示后譬淳,UIKit將更新受影響的視圖控制器的presentingViewController和presentedViewController屬性档址。
清單8-1演示了如何以編程方式呈現(xiàn)視圖控制器。 當(dāng)用戶添加新配方時(shí)邻梆,應(yīng)用程序通過呈現(xiàn)導(dǎo)航控制器來提示用戶關(guān)于配方的基本信息守伸。 選擇了一個(gè)導(dǎo)航控制器,以便有一個(gè)標(biāo)準(zhǔn)的地方放置取消和完成按鈕浦妄。 使用導(dǎo)航控制器還使得將來更容易擴(kuò)展新的配方界面尼摹。 所有你需要做的是在導(dǎo)航堆棧上推新的視圖控制器。
清單8-1以編程方式呈現(xiàn)視圖控制器
- (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];
}
在彈出中呈現(xiàn)視圖控制器
彈出需要額外配置才能顯示它們剂娄。 將模態(tài)表示樣式設(shè)置為UIModalPresentationPopover后蠢涝,請(qǐng)配置以下與彈出相關(guān)的屬性:
- 將視圖控制器的preferredContentSize屬性設(shè)置為所需的大小。
- 使用關(guān)聯(lián)的UIPopoverPresentationController對(duì)象設(shè)置彈出錨點(diǎn)阅懦,該對(duì)象可以從視圖控制器的popoverPresentationController屬性訪問和二。 僅設(shè)置以下選項(xiàng)之一:
* 將barButtonItem屬性設(shè)置為bar按鈕項(xiàng)。
* 將sourceView和sourceRect屬性設(shè)置為其中一個(gè)視圖中的特定區(qū)域耳胎。
您可以使用UIPopoverPresentationController對(duì)象根據(jù)需要對(duì)彈出的外觀進(jìn)行其他調(diào)整惯吕。 彈出呈現(xiàn)控制器還支持一個(gè)委托對(duì)象,您可以使用它來響應(yīng)演示過程中的更改怕午。 例如废登,您可以使用代理在彈出窗口出現(xiàn),消失或在屏幕上重新定位時(shí)進(jìn)行響應(yīng)诗轻。
取消呈現(xiàn)的視圖控制器
要關(guān)閉提交的視圖控制器钳宪,請(qǐng)調(diào)用呈現(xiàn)視圖控制器的dismissViewControllerAnimated:completion:方法。 您還可以在呈現(xiàn)的視圖控制器本身上調(diào)用此方法扳炬。 當(dāng)您在提供的視圖控制器上調(diào)用該方法時(shí),UIKit自動(dòng)將請(qǐng)求轉(zhuǎn)發(fā)到呈現(xiàn)視圖控制器搔体。
在關(guān)閉視圖控制器之前恨樟,始終從視圖控制器保存任何重要信息。 取消視圖控制器會(huì)從視圖控制器層次結(jié)構(gòu)中刪除它疚俱,并從屏幕中刪除它的視圖劝术。 如果您沒有強(qiáng)烈引用存儲(chǔ)在其他位置的視圖控制器,則關(guān)閉它會(huì)釋放與其關(guān)聯(lián)的內(nèi)存呆奕。
如果呈現(xiàn)的視圖控制器必須將數(shù)據(jù)返回給呈現(xiàn)視圖控制器养晋,則使用委托設(shè)計(jì)模式來促進(jìn)傳送。 委托使得在應(yīng)用程序的不同部分中重用視圖控制器更加容易梁钾。 使用委托绳泉,所呈現(xiàn)的視圖控制器存儲(chǔ)對(duì)實(shí)現(xiàn)來自形式協(xié)議的方法的委托對(duì)象的引用。 當(dāng)它收集結(jié)果時(shí)姆泻,呈現(xiàn)的視圖控制器在其委托上調(diào)用這些方法零酪。 在典型的實(shí)現(xiàn)中冒嫡,呈現(xiàn)視圖控制器使其自身成為其呈現(xiàn)的視圖控制器的委托。
雖然可以在同一故事板中的視圖控制器之間創(chuàng)建段四苇,但是不能在故事板之間創(chuàng)建段孝凌。 當(dāng)要顯示存儲(chǔ)在不同故事板中的視圖控制器時(shí),必須在顯示之前顯式地實(shí)例化該視圖控制器月腋,如清單8-2所示蟀架。 該示例以模態(tài)呈現(xiàn)視圖控制器,但您可以將其推送到導(dǎo)航控制器或以其他方式顯示它榆骚。
清單8-2從故事板加載視圖控制器
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];
沒有要求你在應(yīng)用程序中創(chuàng)建多個(gè)故事板辜窑。 這里,雖然寨躁,在少數(shù)情況下穆碎,多個(gè)故事板可能是有用的:
- 你有一個(gè)大型編程團(tuán)隊(duì),用戶界面的不同部分分配給團(tuán)隊(duì)的不同部分职恳。 每個(gè)團(tuán)隊(duì)在不同的故事板文件中擁有其用戶界面的部分所禀,以最小化爭用。
- 你購買或創(chuàng)建了預(yù)定義視圖控制器類型集合的庫; 那些視圖控制器的內(nèi)容在由庫提供的故事板中定義放钦。
- 您的內(nèi)容需要顯示在外部屏幕上色徘。 在這種情況下,您可以將與備用屏幕關(guān)聯(lián)的所有視圖控制器保留在單獨(dú)的故事板中操禀。 同一場(chǎng)景的另一種模式是編寫自定義segue褂策。