UIViewController(三):呈現(xiàn)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

呈現(xiàn)一個(gè)視圖控制器

在屏幕上顯示視圖控制器有兩種方法:將其嵌入到容器視圖控制器中或者呈現(xiàn)它。容器視圖控制器提供了一個(gè)應(yīng)用程序的主要導(dǎo)航菩掏,但正在呈現(xiàn)的視圖控制器也是一個(gè)重要的導(dǎo)航工具。我們可以使用呈現(xiàn)來(lái)在當(dāng)前視圖控制器上層直接顯示一個(gè)新的視圖控制器。通常情況下族展,在實(shí)現(xiàn)模態(tài)界面時(shí),我們需要呈現(xiàn)一個(gè)視圖控制器拔鹰,但也可以將其用于其他目的仪缸。

UIViewController類(lèi)支持呈現(xiàn)一個(gè)視圖控制器,并可用于所有視圖控制器對(duì)象列肢。我們可以使用任何視圖控制器來(lái)呈現(xiàn)其他的任何視圖控制器恰画,但UIKit可能會(huì)將呈現(xiàn)請(qǐng)求重新分配給不同的視圖控制器宾茂。正在呈現(xiàn)的視圖控制器會(huì)在它和呈現(xiàn)它的起始視圖控制器之間創(chuàng)建一種關(guān)系,正在呈現(xiàn)的視圖控制器是起始視圖控制器的presentedViewController拴还,起始視圖控制器是正在呈現(xiàn)的視圖控制器的presentingViewController跨晴。這種關(guān)系構(gòu)成了視圖控制器層次結(jié)構(gòu)的一部分,并保持原樣直到視圖控制器被從屏幕上移除片林。

呈現(xiàn)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)過(guò)程

呈現(xiàn)一個(gè)視圖控制器是將新內(nèi)容動(dòng)畫(huà)化到屏幕上的快捷方式端盆。內(nèi)置于UIKit中的呈現(xiàn)機(jī)制允許我們使用內(nèi)置或者自定義的動(dòng)畫(huà)顯示一個(gè)新的視圖控制器。實(shí)現(xiàn)內(nèi)置的呈現(xiàn)和動(dòng)畫(huà)只需要很少的代碼费封,UIKit會(huì)處理所有的工作焕妙。我們也可以創(chuàng)建自定義的呈現(xiàn)和動(dòng)畫(huà),只需要少許額外處理弓摘,就能將其用于任何視圖控制器访敌。

呈現(xiàn)樣式

視圖控制器的呈現(xiàn)樣式控制其在屏幕上的外觀。UIKit定義了許多標(biāo)準(zhǔn)的呈現(xiàn)樣式衣盾,每種風(fēng)格都有特定的外觀和意圖。我們也可以定義我們自己的自定義呈現(xiàn)樣式爷抓。在設(shè)計(jì)應(yīng)用程序時(shí)势决,請(qǐng)選擇最適合我們正在嘗試呈現(xiàn)的視圖控制器界面的樣式极景,并為視圖控制器的modalPresentationStyle屬性分配合適的值筑累。

全屏樣式

全屏樣式覆蓋整個(gè)屏幕,防止與底層內(nèi)容的交互键闺。在水平常規(guī)環(huán)境中渤昌,只有一種全屏樣式完全覆蓋了底層內(nèi)容虽抄。其他的全屏樣式都包含遮罩視圖或透明視圖,以允許顯示一部分底層視圖控制器独柑。在水平緊湊環(huán)境中迈窟,全屏呈現(xiàn)會(huì)自動(dòng)適應(yīng)UIModalPresentationFullScreen樣式并覆蓋所有底層內(nèi)容。

下圖顯示了在水平常規(guī)環(huán)境中使用UIModalPresentationFullScreen忌栅,UIModalPresentationPageSheetUIModalPresentationFormSheet樣式被呈現(xiàn)的視圖控制器的外觀车酣。在圖中,左上方的綠色視圖控制器呈現(xiàn)右上角的藍(lán)色視圖控制器索绪,每種呈現(xiàn)樣式的結(jié)果如下所示湖员。對(duì)于某些呈現(xiàn)樣式,UIKit會(huì)在兩個(gè)視圖控制器的內(nèi)容之間插入遮罩視圖瑞驱。

圖8-1

注意:使用UIModalPresentationFullScreen樣式來(lái)呈現(xiàn)視圖控制器時(shí)娘摔,UIKit通常會(huì)在轉(zhuǎn)場(chǎng)動(dòng)畫(huà)完成后刪除底層視圖控制器的視圖』椒矗可以通過(guò)指定UIModalPresentationOverFullScreen樣式來(lái)防止刪除底層視圖凳寺。當(dāng)被呈現(xiàn)的視圖控制器具有讓底層視圖內(nèi)容顯示的透明區(qū)域時(shí)鸭津,可以使用此樣式。

當(dāng)使用一種全屏呈現(xiàn)樣式時(shí)读第,起始視圖控制器必須覆蓋整個(gè)屏幕曙博。如果起始視圖控制器沒(méi)有覆蓋整個(gè)屏幕,則UIKit逐步向上查看視圖控制器層次結(jié)構(gòu)怜瞒,直到找到一個(gè)有效的視圖控制器來(lái)全屏呈現(xiàn)另一個(gè)視圖控制器父泳。 如果找不到填充屏幕的中間視圖控制器,則UIKit將使用窗口的根視圖控制器吴汪。

Popover樣式

UIModalPresentationPopover樣式在Popover中顯示視圖控制器惠窄。Popover對(duì)于顯示附加信息或者與焦點(diǎn)、選定對(duì)象相關(guān)的項(xiàng)目列表非常有用漾橙。在水平常規(guī)環(huán)境中杆融,Popover僅覆蓋部分屏幕,如下圖所示霜运。在水平緊湊的環(huán)境中脾歇,默認(rèn)情況下,Popover會(huì)適應(yīng)UIModalPresentationOverFullScreen呈現(xiàn)樣式淘捡。點(diǎn)擊彈出視圖之外的屏幕會(huì)自動(dòng)移除Popover藕各。

圖8-2

因?yàn)镻opover會(huì)自動(dòng)適配在水平緊湊環(huán)境中的全屏呈現(xiàn),所以通常需要修改Popover代碼來(lái)處理適配焦除。在全屏模式下激况,需要一種方法來(lái)移除被呈現(xiàn)的Popover”炱牵可以通過(guò)添加一個(gè)按鈕乌逐,將Popover嵌入到一個(gè)可用的容器視圖控制器中,或者改變適配行為本身创葡。

當(dāng)前上下文樣式

UIModalPresentationCurrentContext樣式覆蓋了界面中的特定視圖控制器浙踢。使用上下文樣式時(shí),通過(guò)將視圖控制器的definesPresentationContext屬性值設(shè)為YES來(lái)指定要覆蓋此視圖控制器蹈丸。下圖顯示了一個(gè)當(dāng)前上下文樣式的呈現(xiàn)成黄,它只覆蓋了分割視圖控制器的一個(gè)子視圖控制器。

圖8-3

注意:當(dāng)使用UIModalPresentationFullScreen樣式來(lái)呈現(xiàn)一個(gè)視圖控制器時(shí)逻杖,UIKit通常會(huì)在轉(zhuǎn)場(chǎng)動(dòng)畫(huà)執(zhí)行完成后刪除處于被呈現(xiàn)的視圖控制器之下的視圖控制器的視圖奋岁。可以通過(guò)指定UIModalPresentationOverCurrentContext樣式來(lái)防止刪除這些視圖荸百。當(dāng)被呈現(xiàn)的視圖控制器具有讓底層內(nèi)容顯示的透明區(qū)域時(shí)闻伶,可以使用該樣式。

定義了呈現(xiàn)上下文的視圖控制器也可以定義在呈現(xiàn)過(guò)程中使用的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)够话。通常情況下蓝翰,UIKit使用起始視圖控制器的modalTransitionStyle屬性值來(lái)在屏幕上動(dòng)畫(huà)視圖控制器光绕。如果呈現(xiàn)上下文視圖控制器的providesPresentationContextTransitionStyle屬性值為YES,則UIKit將使用該視圖控制器的modalTransitionStyle屬性值畜份。

當(dāng)切換到水平緊湊環(huán)境時(shí)诞帐,當(dāng)前上下文樣式會(huì)適應(yīng)UIModalPresentationFullScreen樣式。要更改此行為爆雹,請(qǐng)使用自適應(yīng)呈現(xiàn)委托來(lái)指定不同的呈現(xiàn)樣式或視圖控制器停蕉。

自定義呈現(xiàn)樣式

UIModalPresentationCustom樣式允許我們使用自己定義的自定義樣式來(lái)呈現(xiàn)一個(gè)視圖控制器。創(chuàng)建自定義樣式需要子類(lèi)化UIPresentationController钙态,并使用其方法來(lái)將任何自定義視圖動(dòng)畫(huà)到屏幕上慧起,同時(shí)設(shè)置需要被呈現(xiàn)的視圖控制器的尺寸和位置。起始控制器還處理由于其所呈現(xiàn)的視圖控制器的特性的變化而發(fā)生的任何適應(yīng)册倒。

轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式

轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式確定了用于呈現(xiàn)一個(gè)視圖控制器的動(dòng)畫(huà)類(lèi)型蚓挤。對(duì)于官方提供的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式,可以將其中一種標(biāo)準(zhǔn)樣式分配給需要呈現(xiàn)的視圖控制器的modalTransitionStyle屬性驻子。呈現(xiàn)一個(gè)視圖控制器時(shí)灿意,UIKit會(huì)創(chuàng)建與該樣式相對(duì)應(yīng)的動(dòng)畫(huà)。例如崇呵,下圖說(shuō)明了標(biāo)準(zhǔn)的UIModalTransitionStyleCoverVertical轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式如何為屏幕上的視圖控制器生成動(dòng)畫(huà)脾歧。視圖控制器B開(kāi)始進(jìn)入屏幕時(shí),動(dòng)畫(huà)滑動(dòng)到視圖控制器A的頂部上方演熟。當(dāng)視圖控制器B被移除時(shí),動(dòng)畫(huà)反轉(zhuǎn)司顿,以便B向下滑動(dòng)以顯示A芒粹。

圖8-4

可以使用動(dòng)畫(huà)對(duì)象和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)委托對(duì)象來(lái)創(chuàng)建自定義轉(zhuǎn)場(chǎng)。動(dòng)畫(huà)對(duì)象創(chuàng)建用于將視圖控制器顯示到屏幕上的過(guò)渡動(dòng)畫(huà)大溜。轉(zhuǎn)場(chǎng)動(dòng)畫(huà)委托在適當(dāng)?shù)臅r(shí)候?qū)?dòng)畫(huà)對(duì)象提供給UIKit化漆。

呈現(xiàn)一個(gè)視圖控制器的方式

UIViewController類(lèi)提供了兩種方式來(lái)顯示視圖控制器:

  • showViewController:sender:showDetailViewController:sender:方法提供了最適應(yīng)和最靈活的方式來(lái)顯示視圖控制器。這些方法讓起始控制器決定如何最好地處理呈現(xiàn)钦奋。例如座云,容器視圖控制器可以讓視圖控制器作為一個(gè)子視圖控制器來(lái)呈現(xiàn),而不是以模態(tài)方式呈現(xiàn)付材。默認(rèn)行為以模態(tài)方式呈現(xiàn)一個(gè)視圖控制器朦拖。
  • presentViewController:animated:completion:方式總是模態(tài)顯示視圖控制器。調(diào)用此方法的視圖控制器可能最終不會(huì)處理此次呈現(xiàn)厌衔,但呈現(xiàn)始終是模態(tài)的璧帝。這種方法會(huì)適應(yīng)在水平緊湊環(huán)境中的呈現(xiàn)樣式。

showViewController:sender:showDetailViewController:sender:方法是發(fā)起呈現(xiàn)的首選方式富寿。視圖控制器可以調(diào)用它們而不知道視圖控制器層次結(jié)構(gòu)的其余部分或當(dāng)前視圖控制器在該層次結(jié)構(gòu)中的位置睬隶。這些方法可以在不用編寫(xiě)附帶條件的代碼的情況下锣夹,在應(yīng)用程序的不同部分重新使用視圖控制器。

呈現(xiàn)一個(gè)視圖控制器

有以下幾種方式來(lái)發(fā)起視圖控制器的呈現(xiàn):

  • 使用segue自動(dòng)呈現(xiàn)視圖控制器苏潜。segue使用在Interface Builder中指定的信息來(lái)實(shí)例化并呈現(xiàn)視圖控制器银萍。
  • 使用showViewController:sender:showDetailViewController:sender:方法來(lái)顯示視圖控制器。在自定義視圖控制器中恤左,可以將這些方法的行為更改為更適合我們的視圖控制器的行為贴唇。
  • 調(diào)用presentViewController:animated:completion:方法以模態(tài)方式呈現(xiàn)視圖控制器。

顯示視圖控制器

當(dāng)使用showViewController:sender:showDetailViewController:sender:方法時(shí)赃梧,將新視圖控制器添加到屏幕上的過(guò)程很簡(jiǎn)單:

  • 創(chuàng)建需要呈現(xiàn)的視圖控制器對(duì)象滤蝠。在創(chuàng)建視圖控制器時(shí),需要使用任何需要執(zhí)行其任務(wù)的數(shù)據(jù)對(duì)其進(jìn)行初始化授嘀。
  • 將視圖控制器的modalPresentationStyle屬性設(shè)置為需要的樣式物咳。這種樣式可能不會(huì)在最終呈現(xiàn)中使用。
  • 將視圖控制器的modalTransitionStyle屬性設(shè)置為需要的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式蹄皱。這種樣式可能不會(huì)在最終呈現(xiàn)中使用览闰。
  • 調(diào)用當(dāng)前視圖控制器的showViewController:sender:showDetailViewController:sender:方法。

UIKit會(huì)將對(duì)showViewController:sender:showDetailViewController:sender:方法的調(diào)用轉(zhuǎn)發(fā)給合適的視圖控制器巷折。該視圖控制器可以決定如何最好地執(zhí)行呈現(xiàn)压鉴,并可以根據(jù)需要更改呈現(xiàn)樣式和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式。例如锻拘,導(dǎo)航控制器可能會(huì)將視圖控制器推到其導(dǎo)航堆棧上油吭。

模態(tài)呈現(xiàn)視圖控制器

當(dāng)直接呈現(xiàn)視圖控制器時(shí),需要告訴UIKit如何顯示新的視圖控制器以及如何動(dòng)畫(huà)顯示到屏幕上:

  • 創(chuàng)建需要呈現(xiàn)的視圖控制器對(duì)象署拟。在創(chuàng)建視圖控制器時(shí)婉宰,需要使用任何需要執(zhí)行其任務(wù)的數(shù)據(jù)對(duì)其進(jìn)行初始化。
  • 將視圖控制器的modalPresentationStyle屬性設(shè)置為需要的樣式推穷。
  • 將視圖控制器的modalTransitionStyle屬性設(shè)置為需要的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式心包。
  • 調(diào)用當(dāng)前視圖控制器的presentViewController:animated:completion:方法。

調(diào)用presentViewController:animated:completion:方法的視圖控制器可能不是實(shí)際發(fā)起模態(tài)呈現(xiàn)的視圖控制器馒铃。呈現(xiàn)樣式?jīng)Q定來(lái)如何呈現(xiàn)視圖控制器蟹腾,包括發(fā)起呈現(xiàn)的視圖控制器所需的特性。例如区宇,全屏呈現(xiàn)必須由覆蓋全屏的視圖控制器發(fā)起娃殖。如果當(dāng)前視圖控制器不合適,UIKit將遍歷視圖控制器層次結(jié)構(gòu)议谷,直到找到一個(gè)為止珊随。UIKit在完成模態(tài)呈現(xiàn)后,會(huì)更新受影響的視圖控制器的presentingViewControllerpresentedViewController屬性。

在Popover中呈現(xiàn)一個(gè)視圖控制器

在呈現(xiàn)Popover之前叶洞,需要一些額外配置鲫凶。在設(shè)置模態(tài)呈現(xiàn)樣式為UIModalPresentationPopover后,配置以下與Popover相關(guān)的屬性:

  • 將視圖控制器的preferredContentSize屬性設(shè)置為所需的尺寸衩辟。
  • 訪問(wèn)視圖控制器的popoverPresentationController屬性獲得與其相關(guān)聯(lián)的UIPopoverPresentationController對(duì)象螟炫,并使用該對(duì)象來(lái)設(shè)置Popover的錨點(diǎn)。只需要設(shè)置下列之一:
    • barButtonItem屬性值設(shè)為一個(gè)UIBarButtonItem對(duì)象艺晴。
    • sourceView屬性值設(shè)置為當(dāng)前視圖層中的某個(gè)視圖昼钻,sourceRect屬性值設(shè)置為sourceView中的某個(gè)特定區(qū)域。

可以使用UIPopoverPresentationController對(duì)象根據(jù)需要對(duì)Popover的外觀進(jìn)行其他調(diào)整封寞。Popover控制器對(duì)象還支持設(shè)置委托對(duì)象來(lái)響應(yīng)在呈現(xiàn)過(guò)程中的更改然评。例如,當(dāng)Popover出現(xiàn)狈究、消失或在屏幕上重新定位時(shí)碗淌,可以使用委托對(duì)象來(lái)響應(yīng)。有關(guān)此對(duì)象的更多信息抖锥,可以參閱UIPopoverPresentationController Class Reference亿眠。

移除呈現(xiàn)的視圖控制器

要移除當(dāng)前呈現(xiàn)的視圖控制器,需要調(diào)用該視圖控制器的dismissViewControllerAnimated:completion:方法磅废。也可以調(diào)用呈現(xiàn)該視圖控制器的起始視圖控制器的該方法來(lái)移除當(dāng)前被呈現(xiàn)的視圖控制器纳像。當(dāng)調(diào)用起始視圖控制器的該方法時(shí),UIKit會(huì)自動(dòng)將移除請(qǐng)求轉(zhuǎn)發(fā)給被呈現(xiàn)的視圖控制器拯勉。

在移除視圖控制器之前竟趾,請(qǐng)總是保持視圖控制器中的重要信息。移除視圖控制器會(huì)將其從視圖控制器層次結(jié)構(gòu)中刪除宫峦,并將其視圖從屏幕上移除潭兽。如果沒(méi)有強(qiáng)引用該視圖控制器,移除該視圖控制器將釋放與之關(guān)聯(lián)的內(nèi)存斗遏。

如果呈現(xiàn)的視圖控制器必須傳輸數(shù)據(jù)給發(fā)起呈現(xiàn)的視圖控制器,則使用委托設(shè)計(jì)模式來(lái)促進(jìn)傳輸鞋邑。委托可以使在應(yīng)用程序的不同部分來(lái)重用視圖控制器變得簡(jiǎn)單诵次。使用委托,被呈現(xiàn)的視圖控制器會(huì)存儲(chǔ)對(duì)實(shí)現(xiàn)來(lái)協(xié)議方法的委托對(duì)象的引用枚碗。當(dāng)被呈現(xiàn)的視圖控制器需要接收數(shù)據(jù)時(shí)逾一,其會(huì)調(diào)用委托對(duì)象的協(xié)議方法。

在不同storyboard文件中的視圖控制器之間發(fā)起呈現(xiàn)

可以在同一個(gè)storyboard文件中的視圖控制器之間創(chuàng)建segue肮雨,但不能在不同storyboard文件中的視圖控制器之間創(chuàng)建segue遵堵。當(dāng)需要呈現(xiàn)一個(gè)存儲(chǔ)在不同storyboard文件中的視圖控制器時(shí),必須在呈現(xiàn)其之前明確地實(shí)例化這個(gè)視圖控制器,如下所示陌宿。該示例以模態(tài)方式呈現(xiàn)視圖控制器锡足,但我們也可以將其推到導(dǎo)航堆棧上或以其他方式顯示。

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];

使用Segue

使用segue來(lái)定義應(yīng)用程序界面的跳轉(zhuǎn)流程壳坪。segue定義了storyboard文件中的兩個(gè)視圖控制器之間的轉(zhuǎn)換舶得。segue的起始點(diǎn)是啟動(dòng)segue的按鈕、表格行或者手勢(shì)識(shí)別器爽蝴。segue的結(jié)束點(diǎn)是想要顯示的視圖控制器沐批。segue總是呈現(xiàn)一個(gè)新的視圖控制器,但是也可以使用unwind segue來(lái)移除視圖控制器蝎亚。

圖9-1

不需要以編程方式觸發(fā)segue九孩。在運(yùn)行時(shí),UIKit加載與視圖控制器相關(guān)聯(lián)的segue发框,并將它們連接到相應(yīng)的元素躺彬。當(dāng)用戶與元素產(chǎn)生交互時(shí),UIKit會(huì)加載相應(yīng)的視圖控制器缤底,通知應(yīng)用程序即將觸發(fā)segue顾患,并執(zhí)行轉(zhuǎn)換「鲞螅可以使用UIKit發(fā)送的通知將數(shù)據(jù)傳遞到新的視圖控制器或者防止此種情況發(fā)生江解。

在視圖控制器之間創(chuàng)建一個(gè)segue

要在同一個(gè)storyboard文件中的視圖控制器之間創(chuàng)建一個(gè)segue,請(qǐng)按住Control鍵并單擊第一個(gè)視圖控制器中的相應(yīng)元素徙歼,然后拖動(dòng)到目標(biāo)視圖控制器犁河。segue的起始點(diǎn)必須是具有已經(jīng)定義了action的視圖或者對(duì)象,例如control魄梯、bar button item或者gesture recognizer桨螺。也可以從基于單元格的視圖(如table view和collection view)創(chuàng)建segue。下圖顯示了創(chuàng)建一個(gè)當(dāng)單元格被點(diǎn)擊時(shí)顯示一個(gè)新視圖控制器的segue酿秸。

圖9-2

注意:某些元素支持關(guān)聯(lián)多個(gè)segue灭翔。例如,可以為cell上的button點(diǎn)擊配置一個(gè)segue辣苏,同時(shí)也可以為cell點(diǎn)擊配置另一個(gè)segue肝箱。

當(dāng)松開(kāi)鼠標(biāo)按鈕時(shí),Interface Builder會(huì)提示我們選擇要在兩個(gè)視圖控制器之間創(chuàng)建的關(guān)系類(lèi)型稀蟋,如下圖所示煌张。選擇符合我們需要的轉(zhuǎn)換的segue。

圖9-3

當(dāng)為segue選擇關(guān)系類(lèi)型時(shí)退客,盡可能選擇一個(gè)自適應(yīng)segue骏融。自適應(yīng)segue會(huì)根據(jù)當(dāng)前屏幕環(huán)境調(diào)整其行為链嘀。例如,Show segue的行為基于需要呈現(xiàn)的視圖控制器而改變档玻。非自適應(yīng)segue適用于必須在iOS 7系統(tǒng)運(yùn)行的應(yīng)用程序怀泊。以下列出了自適應(yīng)segue類(lèi)型以及它們?cè)趹?yīng)用程序中的行為:

  • Show (Push) : 該segue使用目標(biāo)視圖控制器的showViewController:sender:方法來(lái)顯示新的內(nèi)容。對(duì)于大多數(shù)視圖控制器窃肠,該segue在源視圖控制器上以模態(tài)方式呈現(xiàn)新內(nèi)容包个。一些視圖控制器專(zhuān)門(mén)覆蓋該方法并使用它來(lái)實(shí)現(xiàn)不同的行為。例如冤留,導(dǎo)航控制器將新的視圖控制器推到其導(dǎo)航堆棧上碧囊。UIKit使用targetViewControllerForAction:sender:方法來(lái)定位源視圖控制器。
  • Show Detail (Replace) : 該segue使用目標(biāo)視圖控制器的showDetailViewController:sender:方法來(lái)顯示新的內(nèi)容纤怒。其僅與嵌入在UISplitViewController對(duì)象內(nèi)的視圖控制器有關(guān)糯而。通過(guò)該segue,分割視圖控制器用新的內(nèi)容替換它的第二個(gè)子視圖控制器(細(xì)節(jié)控制器)泊窘。大多數(shù)其他控制器以模態(tài)方式呈現(xiàn)新內(nèi)容熄驼。UIKit使用targetViewControllerForAction:sender:方法來(lái)定位源視圖控制器。
  • Present Modally : 該segue使用指定的呈現(xiàn)樣式和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)樣式以模態(tài)方式顯示視圖控制器烘豹。定義了相應(yīng)的呈現(xiàn)上下文的視圖控制器會(huì)處理實(shí)際的呈現(xiàn)瓜贾。
  • Present as Popover : 在水平常規(guī)屏幕環(huán)境中,視圖控制器顯示在Popover中携悯。在水平緊湊屏幕環(huán)境中祭芦,視圖控制器使用全屏呈現(xiàn)樣式來(lái)被顯示。

創(chuàng)建一個(gè)segue之后憔鬼,選中segue對(duì)象并使用屬性檢查器為其分配一個(gè)標(biāo)識(shí)符龟劲。在執(zhí)行segue時(shí),可以使用標(biāo)識(shí)符來(lái)確定哪個(gè)segue被觸發(fā)轴或。如果視圖控制器支持多個(gè)segue昌跌,那么這樣做是特別有用的。標(biāo)識(shí)符包含在執(zhí)行segue時(shí)傳遞給視圖控制器的UIStoryboardSegue對(duì)象中照雁。

在運(yùn)行時(shí)修改segue的行為

下圖顯示了當(dāng)一個(gè)segue被觸發(fā)時(shí)發(fā)生了什么蚕愤。大多數(shù)工作發(fā)生在發(fā)起呈現(xiàn)的視圖控制器中,其管理著到新視圖控制器的轉(zhuǎn)場(chǎng)饺蚊。新視圖控制器的配置與以編碼方式創(chuàng)建視圖控制器并呈現(xiàn)它的過(guò)程基本相同萍诱。由于是在storyboard文件中配置segue,所以與segue關(guān)聯(lián)的兩個(gè)視圖控制器必須在同一個(gè)storyboard文件中卸勺。

圖9-4

在執(zhí)行segue期間,UIKit調(diào)用當(dāng)前視圖控制器的方法來(lái)提供機(jī)會(huì)讓我們影響segue的結(jié)果烫扼。

  • shouldPerformSegueWithIdentifier:sender:方法提供了阻止segue執(zhí)行的機(jī)會(huì)曙求。該方法返回NO會(huì)導(dǎo)致segue執(zhí)行失敗,但不會(huì)阻止其他行為的發(fā)生。例如悟狱,點(diǎn)擊tableview的cell仍然會(huì)導(dǎo)致tableview調(diào)用任何相關(guān)的委托方法静浴。
  • 源視圖控制器的prepareForSegue:sender:方法允許我們將數(shù)據(jù)從源視圖控制器傳遞到目標(biāo)視圖控制器。傳遞給該方法的UIStoryboardSegue對(duì)象包含對(duì)目標(biāo)視圖控制器的引用以及其他與segue相關(guān)的信息挤渐。

創(chuàng)建一個(gè)unwind segue

unwind segue能夠移除已經(jīng)被呈現(xiàn)的視圖控制器苹享。可以在Interface Builder中通過(guò)關(guān)聯(lián)一個(gè)按鈕或者其他合適的對(duì)象到當(dāng)前視圖控制器的Exit對(duì)象來(lái)創(chuàng)建unwind segue浴麻。當(dāng)用戶點(diǎn)擊按鈕或者與適當(dāng)?shù)膶?duì)象交互時(shí)得问,UIKit會(huì)搜索視圖控制器層次結(jié)構(gòu)來(lái)找到一個(gè)能夠處理unwind segue的對(duì)象。然后移除當(dāng)前視圖控制器和任何中間視圖控制器來(lái)展示與unwind segue關(guān)聯(lián)的目標(biāo)視圖控制器软免。

創(chuàng)建一個(gè)unwind segue遵循以下步驟:

  1. 選擇unwind segue執(zhí)行結(jié)束后應(yīng)該顯示在屏幕上的視圖控制器宫纬。
  2. 在選擇的視圖控制器中定義一個(gè)unwind 操作方法,這個(gè)操作方法的Objective-C語(yǔ)法為- (IBAction)myUnwindAction:(UIStoryboardSegue*)unwindSegue
  3. 導(dǎo)航到發(fā)起unwind segue的視圖控制器膏萧。
  4. 按住Control鍵點(diǎn)擊執(zhí)行unwind segue的按鈕(或其他對(duì)象)漓骚。該按鈕(或其他對(duì)象)應(yīng)該存在于需要被移除的視圖控制器中。
  5. 拖動(dòng)到視圖控制器頂部的Exit對(duì)象榛泛。
  6. 在relationship panel中選擇unwind操作方法蝌蹂。
圖9-5

在Interface Builder中創(chuàng)建相應(yīng)的unwind segue之前,必須在發(fā)起unwind segue的視圖控制器中定義一個(gè)unwind操作方法曹锨。該方法的存在是必需的孤个,其告知Interface Builder有一個(gè)有效的unwind segue目標(biāo)。

使用unwind操作方法的實(shí)現(xiàn)來(lái)執(zhí)行應(yīng)用程序中特定的任何任務(wù)艘希。UIKit會(huì)自動(dòng)移除視圖控制器硼身,而不需要我們手動(dòng)移除發(fā)起segue的任何視圖控制器「蚕恚可以使用segue對(duì)象獲取正在被移除的視圖控制器佳遂,以便從其中回收數(shù)據(jù)。也可以使用unwind操作方法在unwind segue結(jié)束之前更新當(dāng)前視圖控制器撒顿。

以編程方式發(fā)起segue

segue通常是由在storyboard文件中創(chuàng)建的連接觸發(fā)的丑罪。但是,有時(shí)可能無(wú)法在storyboard文件中創(chuàng)建segue凤壁,可能是因?yàn)闊o(wú)法確定目標(biāo)視圖控制器吩屹。例如,游戲應(yīng)用程序可能會(huì)根據(jù)游戲的結(jié)果轉(zhuǎn)場(chǎng)到不同的界面拧抖。在這些情況下煤搜,可以使用當(dāng)前視圖控制器的performSegueWithIdentifier:sender:方法編程方式出發(fā)segue。

以下代碼演示了從縱向到橫向旋轉(zhuǎn)時(shí)呈現(xiàn)特定視圖控制器的segue唧席。因?yàn)檫@種情況下的通知對(duì)象沒(méi)有提供執(zhí)行segue命令的有用信息擦盾,視圖控制器就將自己指定為segue的發(fā)起者嘲驾。

- (void)orientationChanged:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    
    if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
    {
        [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self];
        
        isShowingLandscapeView = YES;
    }
    // Remainder of example omitted.
}

創(chuàng)建自定義的segue

Interface Builder提供了從一個(gè)視圖控制器轉(zhuǎn)換到另一個(gè)視圖控制器的所有標(biāo)準(zhǔn)方式。如果這些方式不能滿足需求迹卢,也可以創(chuàng)建一個(gè)自定義segue辽故。

segue的生命周期

要理解自定義segue如何工作,就需要了解segue對(duì)象的生命周期腐碱。segue對(duì)象是UIStoryboardSegue類(lèi)或其子類(lèi)的實(shí)例誊垢,應(yīng)用程序永遠(yuǎn)不會(huì)直接創(chuàng)建segue對(duì)象。當(dāng)一個(gè)segue被觸發(fā)時(shí)症见,UIKit會(huì)自動(dòng)創(chuàng)建segue對(duì)象喂走。以下是segue被觸發(fā)時(shí)所發(fā)生的事情:

  1. 創(chuàng)建并初始化需要呈現(xiàn)的視圖控制器。
  2. 創(chuàng)建segue對(duì)象并調(diào)用其initWithIdentifier:source:destination:方法來(lái)初始化筒饰。identifier是在Interface Builder中為segue提供的唯一字符串缴啡,另外兩個(gè)參數(shù)為參與轉(zhuǎn)換的兩個(gè)視圖控制器對(duì)象。
  3. 調(diào)用發(fā)起呈現(xiàn)的視圖控制器的prepareForSegue:sender:方法瓷们。
  4. 調(diào)用segue對(duì)象的perform方法业栅。該方法執(zhí)行轉(zhuǎn)換以將新的視圖控制器顯示在屏幕上。
  5. 釋放被引用的segue對(duì)象谬晕。

實(shí)現(xiàn)一個(gè)自定義segue

為了實(shí)現(xiàn)一個(gè)自定義segue碘裕,需要子類(lèi)化UIStoryboardSegue并實(shí)現(xiàn)以下方法:

  • 覆寫(xiě)initWithIdentifier:source:destination:方法,并使用該方法來(lái)初始化自定義的segue對(duì)象攒钳。需要首先調(diào)用super帮孔。
  • 實(shí)現(xiàn)perform方法并使用該方法來(lái)配置轉(zhuǎn)場(chǎng)動(dòng)畫(huà)。

注意:如果自定義segue類(lèi)中添加了配置segue的屬性不撑,是無(wú)法在Interface Builder中配置這些屬性的文兢。但可以在觸發(fā)segue的源視圖控制器的prepareForSegue:sender:方法中配置自定義segue的附加屬性。

以下代碼展示了一個(gè)簡(jiǎn)單的自定義segue焕檬,其只是簡(jiǎn)單的呈現(xiàn)了目標(biāo)視圖控制器姆坚,沒(méi)有使用任何動(dòng)畫(huà),但可以根據(jù)需要來(lái)擴(kuò)展該它实愚。

- (void)perform
{
    // Add your own animation code here.

    [[self sourceViewController] presentViewController:[self destinationViewController] animated:NO completion:nil];
}

Demo

Demo地址:https://github.com/Jen668/UIViewControllerDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兼呵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子腊敲,更是在濱河造成了極大的恐慌击喂,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碰辅,死亡現(xiàn)場(chǎng)離奇詭異懂昂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)没宾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)凌彬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)潮尝,“玉大人,你說(shuō)我怎么就攤上這事饿序。” “怎么了羹蚣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵原探,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我顽素,道長(zhǎng)咽弦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任胁出,我火速辦了婚禮型型,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘全蝶。我一直安慰自己闹蒜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布抑淫。 她就那樣靜靜地躺著绷落,像睡著了一般。 火紅的嫁衣襯著肌膚如雪始苇。 梳的紋絲不亂的頭發(fā)上砌烁,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音催式,去河邊找鬼函喉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛荣月,可吹牛的內(nèi)容都是我干的管呵。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼喉童,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼撇寞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起堂氯,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蔑担,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后咽白,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體啤握,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年晶框,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了排抬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懂从。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蹲蒲,靈堂內(nèi)的尸體忽然破棺而出番甩,到底是詐尸還是另有隱情,我是刑警寧澤届搁,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布缘薛,位于F島的核電站,受9級(jí)特大地震影響卡睦,放射性物質(zhì)發(fā)生泄漏宴胧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一表锻、第九天 我趴在偏房一處隱蔽的房頂上張望恕齐。 院中可真熱鬧,春花似錦瞬逊、人聲如沸显歧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)追迟。三九已至,卻和暖如春骚腥,著一層夾襖步出監(jiān)牢的瞬間敦间,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工束铭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廓块,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓契沫,卻偏偏與公主長(zhǎng)得像带猴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子懈万,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容