使用segue來(lái)定義應(yīng)用界面流。Segue定義了應(yīng)用storyboard文件中兩個(gè)視圖控制器之間的過(guò)渡。Segue的起點(diǎn)是按鈕、表格行或者發(fā)起segue手勢(shì)識(shí)別器。Segue的終點(diǎn)是你希望顯示的視圖控制器。Segue總是present新視圖控制器,但你還可以使用一個(gè)unwind segue來(lái)dismiss視圖控制器。

你不需要以編程的方式觸發(fā)segue。在運(yùn)行時(shí),UIKit加載視圖控制器相關(guān)的segue并連接它們到相應(yīng)的元素。當(dāng)用戶(hù)與元素交互,UIKit加載適當(dāng)?shù)囊晥D控制器,通知你的應(yīng)用將發(fā)生segue,執(zhí)行過(guò)渡。你可以使用UIKit發(fā)送通知,將數(shù)據(jù)傳遞給新視圖控制器或防止segue發(fā)生。
創(chuàng)建視圖控制器之間的segue
在同一storyboard文件中的視圖控制器之間創(chuàng)建segue,點(diǎn)擊第一個(gè)視圖控制器的適當(dāng)元素并按住Control鍵,拖到目標(biāo)視圖控制器。Segue的起點(diǎn)必須是一個(gè)視圖或?qū)ο螅卸x好的動(dòng)作,如控件、按鈕或手勢(shì)識(shí)別器。你還可以在基于cell的視圖如table和collection視圖上創(chuàng)建segue。圖9-2 展示了如何創(chuàng)建segue,當(dāng)點(diǎn)擊表格某行顯示新視圖控制器。

注意
某些元素支持多個(gè)segue。例如,表格行允許你配置不同的segue用于行accessory按鈕不同的點(diǎn)擊、其他行的點(diǎn)擊。
當(dāng)你釋放鼠標(biāo)按鈕時(shí),界面構(gòu)建器將提示你選擇兩個(gè)視圖控制器間的關(guān)系,如圖9-3所示。選擇segue對(duì)應(yīng)的過(guò)渡。

當(dāng)選擇segue的關(guān)系類(lèi)型,盡量選擇自適應(yīng)segue。自適應(yīng)segue會(huì)自動(dòng)根據(jù)當(dāng)前環(huán)境調(diào)整自己的行為。例如,一個(gè)show類(lèi)型的segue的行為基于present的視圖控制器。提供非自適應(yīng)segue的app必須運(yùn)行在iOS7上,iOS7不支持自適應(yīng)segue。圖9-1列出了自適應(yīng)segue以及他們?cè)趹?yīng)用中的表現(xiàn)。
| Segue類(lèi)型 | 行為 |
|---|---|
| Show (Push) | 這個(gè)segue使用目標(biāo)視圖控制器的showViewController:sender: 方法顯示新內(nèi)容。對(duì)于大多數(shù)視圖控制器,該segue以模態(tài)的方式present新視圖控制器到源視圖控制器上。一些視圖控制器重寫(xiě)該方法,用它來(lái)實(shí)現(xiàn)不同的行為。例如,導(dǎo)航控制器push新視圖控制器到其導(dǎo)航堆棧上。UIKit使用showViewController:sender: 方法定位源視圖控制器。 |
| Show Detail (Replace) | 該sugue使用目標(biāo)視圖控制器的showDetailViewController:sender:方法顯示新內(nèi)容。該segue只用于嵌入到 UISplitViewController對(duì)象的視圖控制器。有了該segue,分屏視圖控制器用新內(nèi)容代替其第二個(gè)子視圖控制器(詳細(xì)視圖控制器)。大多數(shù)其他視圖控制器以模態(tài)的方式present新內(nèi)容。UIKit使用 targetViewControllerForAction:sender:方法定位源視圖控制器。 |
| Present Modally | 該segue使用指定的present和過(guò)渡風(fēng)格,以模態(tài)方式顯示視圖控制器。視圖控制器定義適當(dāng)?shù)膒resent環(huán)境處理實(shí)際present。 |
| Present as Popover | 在水平常規(guī)環(huán)境中,視圖控制器以彈窗的形式出現(xiàn)。在水平緊湊環(huán)境中,全屏present視圖控制器。 |
表9-1 自適應(yīng)segue類(lèi)型
在創(chuàng)建segue后,選擇segue對(duì)象并使用屬性檢查器分配一個(gè)標(biāo)識(shí)符。在segue期間,你可以使用標(biāo)識(shí)符來(lái)確定觸發(fā)那個(gè)segue,如果你的視圖控制器支持多個(gè)segue,這個(gè)方法特別有用。標(biāo)識(shí)符包含在UIStoryboardSegue對(duì)象中,當(dāng)執(zhí)行segue時(shí),會(huì)傳遞給你的視圖控制器。
在運(yùn)行時(shí)修改一個(gè)segue的行為
圖9-4顯示了當(dāng)觸發(fā)segue時(shí)發(fā)生了什么。大部分工作發(fā)生在presenting視圖控制器中,該視圖控制器負(fù)責(zé)到新視圖控制器。新視圖控制器的配置基本遵循相同的步驟,如同你自己創(chuàng)建新視圖控制器并present。因?yàn)閟egue都在storyboard中配置,segue涉及的兩個(gè)視圖控制器必須在同一個(gè)storyboard。

在segue期間,UIKit調(diào)用當(dāng)前視圖控制器的方法來(lái)影響segue結(jié)果。
- shouldPerformSegueWithIdentifier:sender:方法讓你可以組織segue發(fā)生。該方法返回NO會(huì)導(dǎo)致segue失敗但并不阻止其他行為的發(fā)生。例如,點(diǎn)擊表中的行仍然會(huì)導(dǎo)致表調(diào)用代理相關(guān)方法。
- 源視圖控制器的 prepareForSegue:sender: 方法讓你可以傳遞源視圖控制器的數(shù)據(jù)到目標(biāo)視圖控制器。傳遞到該方法的UIStoryboardSegue對(duì)象包含目標(biāo)視圖控制器的引用以及其他segue相關(guān)的信息。
創(chuàng)建一個(gè)unwind segue
unwind segue可以dismiss已present的視圖控制器。在界面構(gòu)建器中,通過(guò)鏈接按鈕或其他合適的對(duì)象到當(dāng)前視圖控制器Exit對(duì)象上創(chuàng)建unwind segue。當(dāng)用戶(hù)點(diǎn)擊該按鈕或界面上適當(dāng)對(duì)象,UIKit在視圖控制器層級(jí)上搜索能處理unwind segue的對(duì)象。然后它dismiss當(dāng)前視圖控制器和任何顯示unwind segue目標(biāo)的中間視圖控制器。
創(chuàng)建unwind segue
- 在unwind segue的末端選擇要在屏幕上顯示的視圖控制器。
- 在你選擇的視圖控制器中定義一個(gè)unwind動(dòng)作方法。
該方法的swift語(yǔ)法如下:
<pre><code>
@IBAction func myUnwindAction(unwindSegue: UIStoryboardSegue)
</pre></code>
該方法的Objective-C語(yǔ)法如下:
<pre><code>- (IBAction)myUnwindAction:(UIStoryboardSegue*)unwindSegue</pre></code>
- 導(dǎo)航到啟動(dòng)unwind動(dòng)作的視圖控制器上。
- Control-click啟動(dòng)unwind segue的按鈕(或其他對(duì)象)。該元素必須在你希望dismiss 的視圖控制器上。
- 拖動(dòng)到視圖控制器場(chǎng)景頂部的Exit對(duì)象。

- 在關(guān)系面板上選擇unwind動(dòng)作方法。
試圖在界面構(gòu)建器上創(chuàng)建相應(yīng)的unwind seuge之前,必須在視圖控制器上定義一個(gè)unwind 動(dòng)作方法。該方法是必須的,告訴界面構(gòu)建器有unwind segue有一個(gè)有效的目標(biāo)。
使用unwind 動(dòng)作方法的實(shí)現(xiàn)來(lái)執(zhí)行app的特定任務(wù)。你不需要dismiss任何參與segue的視圖控制器;UIKit為你做了。相反,使用segue對(duì)象可以獲取被dismiss的視圖控制器,這樣你可以檢索數(shù)據(jù)。還可以使用unwind動(dòng)作在unwind segue完成前更新當(dāng)前視圖控制器。
以編程的方式啟動(dòng)segue
segue經(jīng)常因?yàn)閟toryboard文件中創(chuàng)建的連接而觸發(fā)。然而,有些時(shí)候你不能在storyboard中創(chuàng)建segue,可能因?yàn)槟繕?biāo)視圖控制器沒(méi)有確定。例如,一個(gè)游戲應(yīng)用可能根據(jù)游戲結(jié)果過(guò)渡到不同界面。在這些情況下,你可以使用當(dāng)前視圖控制器的 performSegueWithIdentifier:sender:方法,以編程的方式觸發(fā)segue。
列表9-1展示了從豎屏旋轉(zhuǎn)到橫屏?xí)r,present特定視圖控制器的segue。因?yàn)樵谶@種情況中,通知對(duì)象沒(méi)有提供有用的信息來(lái)執(zhí)行segue命令,視圖控制器指定自己作為segue的sender。
列表9-1 以編程的方式觸發(fā)segue
<pre><code>- (void)orientationChanged:(NSNotification *)notification {
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView) {
[self performSegueWithIdentifier:@"DisplayAlternateView" sender:self];
isShowingLandscapeView = YES;
}
// Remainder of example omitted.
}
// Remainder of example omitted.
}
</pre></code>
創(chuàng)建自定義segue
界面構(gòu)建器提供segue的標(biāo)準(zhǔn)用法:從一個(gè)視圖控制器到另一個(gè)視圖控制器的過(guò)渡或者在presenting視圖控制器上以彈窗的方式顯示控制器。然而,如果segue不滿(mǎn)足你的需求,你可以創(chuàng)建一個(gè)自定義segue。
segue生命周期
了解如何自定義segue,你需要理解segue對(duì)象的生命周期。segue對(duì)象是UIStoryboardSegue類(lèi)實(shí)例或其子類(lèi)。應(yīng)用不要直接創(chuàng)建segue;當(dāng)觸發(fā)sugue時(shí)UIKit會(huì)創(chuàng)建該對(duì)象。
- 創(chuàng)建和初始化presented視圖控制器。
- 創(chuàng)建segue對(duì)象并調(diào)用其 initWithIdentifier:source:destination: 方法。在界面構(gòu)建器中設(shè)置segue的標(biāo)識(shí)符是唯一的字符串,另外兩個(gè)參數(shù)代表了過(guò)渡中的兩個(gè)視圖控制器對(duì)象。
- 調(diào)用presenting視圖控制器的 prepareForSegue:sender: 方法,參見(jiàn)運(yùn)行時(shí)修改segue行為( Modifying a Segue’s Behavior at Runtime)。
- 調(diào)用segue對(duì)象的 perform方法。該方法執(zhí)行一個(gè)過(guò)渡到新視圖控制器。
- segue對(duì)象的引用被釋放。
實(shí)現(xiàn)自定義segue
實(shí)現(xiàn)一個(gè)自定義segue,繼承 UIStoryboardSegue并實(shí)現(xiàn)以下方法:
- 覆蓋
initWithIdentifier:source:destination:方法并用它來(lái)初始化自定義segue對(duì)象??偸且日{(diào)用super方法。 - 實(shí)現(xiàn)perform方法并用它來(lái)配置過(guò)渡動(dòng)畫(huà)。
注意
如果實(shí)現(xiàn)添加屬性來(lái)配置segue,你不能在界面構(gòu)建器中配置這些屬性。相反,可以在觸發(fā)segue的源視圖控制器的 prepareForSegue:sender: 方法中配置自定義segue的附加屬性。
列表9-2展示了一個(gè)非常簡(jiǎn)單的自定義segue。這個(gè)例子簡(jiǎn)單的present目標(biāo)視圖控制器而沒(méi)有任何形式的動(dòng)畫(huà),但你可以擴(kuò)展實(shí)現(xiàn)自己的動(dòng)畫(huà)。
列表9-2 自定義segue
<pre><code>- (void)perform {
// Add your own animation code here.
[[self sourceViewController] presentViewController:[self destinationViewController] animated:NO completion:nil];
}
</pre></code>