第十二章 介紹導(dǎo)航控制器和segue

構(gòu)建你今天想要用的東西就好,而不是你覺(jué)得人們?cè)谀撤N程度上會(huì)使用的東西柳沙。
— Paul Graham

首先窟赏,什么是導(dǎo)航控制器妓柜?比如 table views。導(dǎo)航控制器在 iOS應(yīng)用是另一個(gè)自定義 UI部分涯穷。它為分層內(nèi)容提供了一個(gè)向下的界面棍掐。看看內(nèi)置照片應(yīng)用拷况,YouTube和記事本作煌。他們都使用導(dǎo)航控制器來(lái)顯示分層內(nèi)容。一般蝠嘉,你用一個(gè)視圖控制器的堆棧與導(dǎo)航控制器聯(lián)合起來(lái)為你的應(yīng)用構(gòu)建一個(gè)盡量簡(jiǎn)潔的界面最疆。盡管如此,這不意味著你必須一起使用它們蚤告。導(dǎo)航控制器可以和任何風(fēng)格的視圖控制器一起工作努酸。

Storyboards里的場(chǎng)景(Scenes)和延續(xù)(Segues)

直到現(xiàn)在,我們僅僅在 FoodPin應(yīng)用的 Storyboard里布局了一個(gè) table view 控制器杜恰。Storyboard允許你做得更多获诈。你可以在 storyboard 里添加更多的視圖控制器來(lái)連接他們。所有這些工作能夠在沒(méi)有一行代碼的情況下完成心褐。當(dāng)用 storyboards 工作時(shí)舔涎,場(chǎng)景(scenes)和延續(xù)(segues)是你必須知道的兩項(xiàng)。在 storyboard 里逗爹,一個(gè)場(chǎng)景通常涉及到屏幕上內(nèi)容(如一個(gè)視圖控制器)亡嫌。segues位于2個(gè)場(chǎng)景之間,表示一個(gè)場(chǎng)景到另一個(gè)的切換掘而。Push 和 Modal 是兩種常見(jiàn)類(lèi)型的轉(zhuǎn)變挟冠。

Quick note:在 Xcode7里,介紹一個(gè)新的特性叫做 storyboard references袍睡,這個(gè)參考讓 storyboards 更易于管理和更模塊化知染。當(dāng)你的工程變得大而復(fù)雜時(shí),你可以把一個(gè)大的 storyboard分割成多個(gè) storyboard 然后用 storyboard references連接他們斑胜。當(dāng)你和你的團(tuán)隊(duì)成員合作創(chuàng)建一個(gè) storyboard 時(shí)這個(gè)特性是特別有用的控淡。

創(chuàng)建導(dǎo)航控制器

我們將通過(guò)內(nèi)嵌table view 控制器進(jìn)入一個(gè)導(dǎo)航控制器來(lái)繼續(xù)在 Food Pin應(yīng)用上工作嫌吠。當(dāng)一個(gè)用戶(hù)選擇任何餐廳時(shí),這個(gè)應(yīng)用導(dǎo)航到下個(gè)屏幕來(lái)顯示餐廳細(xì)節(jié)掺炭。



如果你已經(jīng)關(guān)閉了 FoodPin 工程辫诅,現(xiàn)在是時(shí)候打開(kāi) Xcode 然后再次打開(kāi)工程。選擇 Main.storyboard 來(lái)切換到界面構(gòu)建器編輯竹伸。Xcode 提供一個(gè)內(nèi)嵌特性來(lái)使它在一個(gè)導(dǎo)航控制器里很容易嵌入任何視圖控制器泥栖。選擇 table view 控制器然后點(diǎn)擊菜單里的”Editor”。選擇“Embed in”>“Navigation Controller”勋篓。


Xcode 自動(dòng)在一個(gè)導(dǎo)航控制器嵌入控制器吧享。我們?cè)O(shè)置導(dǎo)航欄的標(biāo)題。選擇 table view 控制器的導(dǎo)航欄譬嚣。在 Attributes inspector 下钢颂,把title 值改成 Food Pin。


現(xiàn)在運(yùn)行應(yīng)用看看它看起來(lái)如何拜银。這個(gè)應(yīng)用和以前一樣殊鞭,但是添加了一個(gè)導(dǎo)航欄。

添加一個(gè)視圖控制器細(xì)節(jié)

很簡(jiǎn)單尼桶,對(duì)嗎操灿??jī)H僅點(diǎn)幾下,你已經(jīng)給你的應(yīng)用添加一個(gè)導(dǎo)航欄泵督。不過(guò)這里漏掉了顯示餐廳細(xì)節(jié)的視圖控制器趾盐。當(dāng)用戶(hù)選擇一個(gè)餐廳,應(yīng)用傳遞給細(xì)節(jié)視圖控制器然后顯示餐廳細(xì)節(jié)小腊。
在視圖構(gòu)建器里救鲤,從對(duì)象控制器里拖出一個(gè)視圖控制器來(lái)創(chuàng)建細(xì)節(jié)視圖控制器。我們讓細(xì)節(jié)視圖越簡(jiǎn)單越好秩冈。我們僅僅在細(xì)節(jié)視圖里顯示餐廳照片本缠。從對(duì)象庫(kù)里拖曳一個(gè)圖像視圖到視圖控制器。調(diào)整它的大小來(lái)適應(yīng)適合入问,然后添加為圖像視圖添加間距約束丹锹。為了確保圖片正確的縮放,進(jìn)入 Attributes inspector 把 mode從 Scale to Fill 改成 Aspect Fill芬失。


現(xiàn)在你在 storyboard 里配置了兩個(gè)視圖控制器卷仑。這里有個(gè)問(wèn)題,你如何才能把他們連接在一起麸折?在 storyboard 里,我們需要通過(guò)一個(gè) segue 來(lái)連接他們粘昨。在音樂(lè)方面垢啼,一個(gè) segue 是兩段音樂(lè)之間無(wú)縫的過(guò)渡窜锯。在 storyboard 里, 兩個(gè)場(chǎng)景之間的過(guò)渡叫做 segue芭析。
當(dāng)用戶(hù)按下單元格時(shí)锚扎,table view 控制器將傳遞到細(xì)節(jié)場(chǎng)景。所以我們將添加一個(gè) segue 來(lái)連接 prototype cell 和細(xì)節(jié)場(chǎng)景馁启。添加一個(gè) segue 對(duì)象是很容易的驾孔。按住 control 鍵,點(diǎn)擊 prototype cell 然后拖到細(xì)節(jié)視圖控制器惯疙。


如果你覺(jué)得在 storyboard editor 里選擇 prototype cell 很難翠勉,打開(kāi)文檔大綱視圖,把 prototype cell 拖到 view controller霉颠。當(dāng)你松開(kāi)按鈕時(shí)对碌,一個(gè)彈出菜單會(huì)出現(xiàn),給你來(lái)選擇 segue 的類(lèi)型蒿偎。選擇類(lèi)型為“Show”朽们,然后你會(huì)看到在 view controller 之間有一個(gè)接頭。


一旦選好了诉位,Xcode 用一個(gè) show segue自動(dòng)連接 prototype cell 和細(xì)節(jié)視圖控制器骑脱。


在 iOS9里,它支持以下的 segue 類(lèi)型:

  • Show - 當(dāng)使用 show 類(lèi)型時(shí)苍糠,內(nèi)容被推送到當(dāng)前視圖控制器堆棧的頂上叁丧。一個(gè)返回按鈕將顯示在導(dǎo)航欄來(lái)返回原始視圖控制器。我們?yōu)閷?dǎo)航控制器使用這個(gè) segue 類(lèi)型椿息。
  • Show detail - 類(lèi)似于 show 類(lèi)型歹袁,但是細(xì)節(jié)(或目標(biāo))視圖控制器里的內(nèi)容取代當(dāng)前視圖控制器堆棧的頂部。例如寝优,如果你在 FoodPin 應(yīng)用 里選擇show detail 而不是 show条舔,那樣在細(xì)節(jié)視圖里將沒(méi)有導(dǎo)航欄和返回按鈕。
  • Present modally - 程序化的顯示內(nèi)容乏矾。使用時(shí)孟抗,細(xì)節(jié)視圖控制器將從底部開(kāi)始動(dòng)畫(huà)效果然后覆蓋整個(gè) iphone屏幕。一個(gè)“present modally”segue 的好例子是內(nèi)置日歷應(yīng)用 的“add”特性钻心。當(dāng)你點(diǎn)擊應(yīng)用里的+按鈕時(shí)凄硼,它會(huì)從底部引出一個(gè)“新事件”。
  • Present as popover - 作為一個(gè)彈窗固定到現(xiàn)有的視圖來(lái)呈現(xiàn)內(nèi)容捷沸。Popover 通常能在 iPad 應(yīng)用中找到摊沉。下圖為你顯示了一個(gè)例子。從 iOS8開(kāi)始痒给,你也可以在 iPhone 應(yīng)用上使用 popover segue说墨。

Quick note:這些 segue 類(lèi)型從 iOS8開(kāi)始被棄用:Push骏全,Modal,Popover尼斧,Replace姜贡。


現(xiàn)在,你可以準(zhǔn)備運(yùn)行應(yīng)用棺棵。登陸時(shí)楼咳,選擇一個(gè)餐廳,應(yīng)用應(yīng)該會(huì)導(dǎo)航到細(xì)節(jié)視圖控制器烛恤。同時(shí)母怜,細(xì)節(jié)視圖控制器僅僅顯示一個(gè)黑色的屏幕。好的消息是你已經(jīng)創(chuàng)建了一個(gè)導(dǎo)航界面棒动。
沒(méi)有寫(xiě)一行代碼糙申,你已經(jīng)在你的應(yīng)用里添加了一個(gè)導(dǎo)航控制器。但是船惨,我猜在你的腦海里會(huì)有一些疑問(wèn):

  • 你如何才能從 RestaurantTableViewController 傳遞餐廳信息到細(xì)節(jié)視圖控制器柜裸?
  • 你如何才能在細(xì)節(jié)視圖控制器里顯示選擇的餐廳圖片。
    我們待會(huì)將會(huì)一個(gè)個(gè)的解決它們粱锐。
    在進(jìn)入下一章之前疙挺,我們來(lái)做一點(diǎn)小的調(diào)整。當(dāng)你運(yùn)行應(yīng)用程序選擇一個(gè)單元格時(shí)怜浅,它會(huì)導(dǎo)航到空白的屏幕铐然,顯示一個(gè)我們?cè)?jīng)在第十章實(shí)現(xiàn)的動(dòng)作表單。我們不再需要那個(gè)動(dòng)作表單恶座。之后我們將在細(xì)節(jié)視圖控制器里添加相同的功能搀暑。因此,從 RestaurantTableViewController.swift 里移除 tableView(_:didSelectRowAtIndexPath:) 方法跨琳。

Quick tip:有時(shí)你可能僅僅想要注釋掉一個(gè)代碼塊而不是刪除它們自点。Xcode 提供一個(gè)快捷鍵來(lái)注釋多行代碼。首先脉让,選擇代碼塊然后按住 command+slash桂敛。Xcode 會(huì)自動(dòng)用注釋指示器標(biāo)記(comment indicators)代碼塊。想要移除注釋?zhuān)僮鲆淮瓮瑯拥某绦颉?/p>

為細(xì)節(jié)視圖控制器創(chuàng)建一個(gè)新的類(lèi)

Okay溅潜,我們回到細(xì)節(jié)視圖控制器术唬。我們的目標(biāo)是在視圖控制器里為被選擇的餐廳更新圖片。視圖控制器現(xiàn)在默認(rèn)與 UIViewController 類(lèi)相連滚澜。事實(shí)是 UIViewController 類(lèi)僅僅提供基本的視圖管理模式粗仓。這里面沒(méi)有變量用于儲(chǔ)存餐廳圖片。明顯的,我們必須擴(kuò)展 UIViewController 來(lái)創(chuàng)建我們自己的類(lèi)以便于我們能為圖片視圖添加新的變量借浊。
在工程導(dǎo)航器里眶掌,右擊”FoodPin”文件夾然后選擇”New File…”。選擇”Cocoa Touch Class”作為類(lèi)模板巴碗。把這個(gè)類(lèi)命名為 RestaurantTableViewController 然后把它設(shè)置為 UIViewController 的一個(gè)子類(lèi)。點(diǎn)擊”Next”然后在你的工程文件夾里保存文件即寒。


和平常一樣橡淆,分配 DetailViewController 類(lèi)到 storyboard 里的細(xì)節(jié)視圖控制器。在界面構(gòu)建器里母赵,選擇細(xì)節(jié)視圖控制器然后打開(kāi) Identity inspector逸爵。改變自定義類(lèi)到 RestaurantTableViewController。

給自定義類(lèi)添加變量

我們必須在自定義類(lèi)里添加一堆東西:

  • 創(chuàng)建一個(gè)變量叫做 restaurantImage — 當(dāng)用戶(hù)在 table view 控制器里選擇一個(gè)餐廳時(shí)凹嘲,應(yīng)該有個(gè)辦法來(lái)傳遞圖片名給細(xì)節(jié)視圖师倔。這個(gè)變量將被用于數(shù)據(jù)傳遞。
  • 為圖片視圖創(chuàng)建一個(gè)叫做 restaurantImageView 的outlet — 我們需要一個(gè)參考來(lái)更新細(xì)節(jié)圖像控制器的圖像視圖周蹭,所以我們不得不創(chuàng)建一個(gè) outlet趋艘。
    Okay,給 RestaurantTableViewController 類(lèi)添加下面的代碼凶朗。

@IBOutlet var restaurantImageView:UIImageView!
var restaurantImage = “”

接下來(lái)瓷胧,在 restaurantImageView 變量和細(xì)節(jié)視圖控制器的圖片視圖之間建立聯(lián)系∨锓撸回到 Main.storyboard搓萧。右擊文檔大綱里的Restaurant Detail View Controller對(duì)象。在彈出菜單里宛畦,連接 restaurantImageView outlet 和圖像視圖控制器瘸洛。


既然你已經(jīng)聯(lián)系了變量和故事板里的圖像視圖對(duì)象,但是仍然有一件事沒(méi)做次和。你還沒(méi)有讀取圖片反肋。圖片視圖應(yīng)該顯示被選擇的餐廳圖片。在RestaurantTableViewController 類(lèi)的 viewDidLoad 方法里斯够,添加一行代碼囚玫。你的方法應(yīng)該看起來(lái)像這樣:

overrid func viewDidLoad() {
super.viewDidLoad()
//加載視圖后做任何額外的設(shè)置。
restaurantImageView.image = UIImage(named:restaurantImage)
}

當(dāng)視圖加載到內(nèi)存里時(shí)读规,viewDidLoad 方法被調(diào)用抓督。在這個(gè)方法里,你能提供額外的自定義視圖束亏。在上面铃在,我們簡(jiǎn)單的設(shè)置圖像視圖的圖像給被選擇餐廳的圖像。
試著編譯運(yùn)行你的應(yīng)用。在選擇一個(gè)餐廳之后這個(gè)細(xì)節(jié)視圖仍然是空白的定铜。我們?nèi)匀桓沐e(cuò)了一件事阳液。我們沒(méi)有從 table view控制器傳遞餐廳圖像到細(xì)節(jié)視圖控制器。這是為什么 restaurantImage 變量沒(méi)有被分配任何值揣炕。

用 segues 傳遞數(shù)據(jù)

接下來(lái)是本章的核心部分帘皿,關(guān)于用 segues 傳遞數(shù)據(jù)。一個(gè) segue 管理視圖控制器之間的傳遞畸陡,包含了涉及到過(guò)渡的視圖控制器鹰溜。當(dāng)一個(gè) segue 觸發(fā)時(shí),在可視化過(guò)渡出現(xiàn)之前丁恭,storyboard 運(yùn)行時(shí)通過(guò)調(diào)用 prepareForSegue 方法通知源視圖控制器(如R estaurantTableViewController).默認(rèn)prepareForSegue 方法的實(shí)施沒(méi)做任何事曹动。通過(guò)重寫(xiě)方法,你可以傳遞任何相關(guān)數(shù)據(jù)到新的控制器牲览,這個(gè)控制器在我們工程叫做 RestaurantDetailViewController墓陈。
segues 可以被很多來(lái)源觸發(fā)。隨著你的 storyboard 變得更復(fù)雜第献,在視圖控制器之間你有超過(guò)一個(gè)的 segue是很有可能的贡必。因此,最好的實(shí)踐是給每個(gè)在 storyboard 里的 segue 一個(gè)唯一的標(biāo)識(shí)符痊硕。這個(gè)標(biāo)識(shí)符是一個(gè)字符串赊级,用來(lái)區(qū)分 segue。為一個(gè) segue 分配一個(gè)標(biāo)識(shí)符岔绸,在 storyboard 編輯器里選擇這個(gè) segue理逊,然后進(jìn)入 Attributes inspector。設(shè)置 identifier 值為 showRestaurantDetail盒揉。


隨著配置好 segue晋被,插入以下在 RestaurantTableViewController.swift 里的代碼來(lái)重寫(xiě) prepareForSegue 方法的默認(rèn)實(shí)施:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == “showRestaurantDetail” {
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as!
RestaurantDetailViewController
destinationController.restaurantImage = restaurantImages[indexPath.row]
}
}
}

第一行代碼被用來(lái)核查 segue 的標(biāo)識(shí)符。這個(gè)代碼塊僅僅對(duì) showRestaurantDetail segue 生效刚盈。在代碼塊里羡洛,我們首先通過(guò)訪(fǎng)問(wèn) tableView.indexPathForSelectedRow 來(lái)檢索選擇的行。indexPath 對(duì)象應(yīng)該包含選擇的單元格藕漱。
一個(gè) segue 對(duì)象同時(shí)包含源和目標(biāo)視圖控制器來(lái)參與過(guò)渡欲侮。你使用segue.destinationViewController來(lái)檢索目標(biāo)控制器。在這種情況下肋联,目標(biāo)控制器是 RestaurantDetailViewController對(duì)象威蕉。這就是為什么我們必須用 as! 操作符來(lái)向下轉(zhuǎn)換它。最終橄仍,我們傳遞選擇餐廳的圖片到目標(biāo)控制器韧涨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末牍戚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虑粥,更是在濱河造成了極大的恐慌如孝,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娩贷,死亡現(xiàn)場(chǎng)離奇詭異第晰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)彬祖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)但荤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人涧至,你說(shuō)我怎么就攤上這事∩0” “怎么了南蓬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)哑了。 經(jīng)常有香客問(wèn)我赘方,道長(zhǎng),這世上最難降的妖魔是什么弱左? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任窄陡,我火速辦了婚禮,結(jié)果婚禮上拆火,老公的妹妹穿的比我還像新娘跳夭。我一直安慰自己,他們只是感情好们镜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布币叹。 她就那樣靜靜地躺著,像睡著了一般模狭。 火紅的嫁衣襯著肌膚如雪颈抚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天嚼鹉,我揣著相機(jī)與錄音贩汉,去河邊找鬼。 笑死锚赤,一個(gè)胖子當(dāng)著我的面吹牛匹舞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宴树,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼策菜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起又憨,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤翠霍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蠢莺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寒匙,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年躏将,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锄弱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祸憋,死狀恐怖会宪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚯窥,我是刑警寧澤掸鹅,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拦赠,受9級(jí)特大地震影響巍沙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荷鼠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一句携、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧允乐,春花似錦矮嫉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至麸澜,卻和暖如春挺尿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炊邦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工编矾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人馁害。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓窄俏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親碘菜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凹蜈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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