Storyboards 使用指南 iOS 9: 第一部分

這是一篇翻譯作品,水平有限,希望各位指正启上。各位同學(xué)最好去看原文:
Storyboards Tutorial in iOS 9: Part 1

注意:在04-01-2016更新了Xcode 7.3,iOS 9.3和Swift 2.2
教程團(tuán)隊(duì)成員Matthijs Hollemans原始貼子

故事板是一個(gè)令人興奮的功能猖败,在iOS 5首次引入肋拔,為你構(gòu)建用戶界面節(jié)省大量的時(shí)間思喊。
讓我用一張圖片向你展示storyboard是什么言沐,這就是你在指南中你在教程中將要構(gòu)建的故事板:



你可能不知道這個(gè)應(yīng)用程序的功能邦投,但你可以清楚地看到它有哪些場(chǎng)景伤锚,以及它們是如何關(guān)聯(lián)的。
故事板有許多優(yōu)點(diǎn):

  • 您可以在“場(chǎng)景”中直觀地布置所有視圖控制器志衣,并說(shuō)明它們之間的關(guān)聯(lián)關(guān)系见芹。使用故事板可以更好的概述您的應(yīng)用程序的所有場(chǎng)景。
  • 故事板可以描述各種場(chǎng)景的轉(zhuǎn)場(chǎng)蠢涝。這些轉(zhuǎn)場(chǎng)被稱為"segues",您可以通過(guò)在故事板中連接視圖控制器來(lái)創(chuàng)建它們阅懦。感謝"segues"讓你需要更少的代碼來(lái)照顧你的UI和二。
  • 故事板通過(guò)原型單元格和靜態(tài)單元格功能,可以更輕松地處理表格視圖耳胎。您幾乎可以完全在故事板編輯器中完成您的表格視圖設(shè)計(jì)惯吕,從而減少您必須編寫的代碼量惕它。
  • 故事板使您更容易使用自動(dòng)布局,該功能允許您定義定義其位置和大小的元素之間的數(shù)學(xué)關(guān)系废登。這個(gè)強(qiáng)大的功能使得更容易處理不同屏幕尺寸和尺寸的設(shè)備淹魄。在本教程中,您將使用“自動(dòng)布局”堡距,但不在本教程的范圍之內(nèi)甲锡。您可以在自動(dòng)布局教程 或者 觀看視頻系列獲取更多信息。

在這個(gè)故事板的教程中羽戒,你創(chuàng)建一個(gè)簡(jiǎn)單的應(yīng)用程序缤沦,可以讓你創(chuàng)建一個(gè)游戲和玩家列表,并評(píng)估他們的技能水平易稠。在這個(gè)過(guò)程中缸废,你將學(xué)會(huì)用故事版完成最常見(jiàn)的任務(wù)。

入門

啟動(dòng)Xcode并創(chuàng)建一個(gè)新項(xiàng)目驶社。使用單視圖應(yīng)用程序模板作為起點(diǎn)企量。


填寫模板選項(xiàng)如下:

  • Product Name: Ratings
  • Organization Name: fill this in however you like
  • Organization Identifier: the identifier that you use for your apps
  • Language: Swift
  • Devices: iPhone
  • Use Core Data: not checked
  • Include Unit Tests and UI Tests: not checked

Xcode創(chuàng)建項(xiàng)目后,Xcode主窗口看起來(lái)這樣:



新項(xiàng)目包含兩個(gè)類亡电,AppDelegate 和 ViewController届巩,本教程的主角:Main.storyboard文件。
這是一個(gè)只有肖像的應(yīng)用程序逊抡,繼續(xù)之前姆泻,找到 Deployment Info > Device Orientation取消屏幕左右旋轉(zhuǎn)選項(xiàng)。
讓我們看一看這個(gè)storyboard文件冒嫡。在項(xiàng)目導(dǎo)航欄中點(diǎn)擊storyboard文件打開(kāi)它拇勃,在界面生成器編輯器:



一個(gè)視圖控制器的官方故事板術(shù)語(yǔ)是“場(chǎng)景”,但你可以互換使用這些術(shù)語(yǔ)孝凌。在故事板中一個(gè)場(chǎng)景代表一個(gè)視圖控制器方咆。

這里您可以看到一個(gè)包含空視圖的單視圖控制器。在視圖控制器的左側(cè)有箭頭指向表明蟀架,它是故事板的最開(kāi)始顯示的視圖控制器瓣赂。

在故事板編輯器中構(gòu)建布局是從對(duì)象庫(kù)通過(guò)拖動(dòng)控件到你的視圖控制器完成(見(jiàn)右下角)的。

注意:你會(huì)注意到默認(rèn)場(chǎng)景大小是一個(gè)正方形片拍。Xcode 7在故事板中使用Auto Layout and Size Classes. Auto Layout and Size Classes允許您制作靈活的用戶界面重抖,可以方便地調(diào)整大小敢辩,這對(duì)于支持各種大小的iPhone和iPad都很有用。去更多的學(xué)習(xí)Size Classes,看看我們的Adaptive Layout video tutorial series.
在這個(gè)教程中,你可以選擇故事板的大小莫绣,這樣可以更容易地了解最終屏幕上的布局。

在你開(kāi)始之前,調(diào)整模擬器場(chǎng)景大小為iPhone 6 /6。
在視圖列表中選擇View Controller喊废。如果你沒(méi)有看到“視圖列表”,單擊故事板畫布左下角的這個(gè)按鈕:


選擇Attributes Inspector下的Simulated Metrics,改變SizeiPhone 4.7 inch.

在storyboard的場(chǎng)景將顯示尺寸為iPhone 6/6S栗弟,大小為4.7英寸的iPhone模擬器污筷。
“推斷”是在故事板的模擬器指標(biāo)的默認(rèn)設(shè)置。模擬器的指標(biāo)是storyboard的視覺(jué)設(shè)計(jì)助手,展示最終設(shè)計(jì)界面乍赫。記住瓣蛀,他們不是在運(yùn)行時(shí)使用的。

去感受storyboard的編輯過(guò)程耿焊。從右下角的對(duì)象庫(kù)拖動(dòng)一些控件到空白視圖控制器揪惦。



當(dāng)拖動(dòng)控件時(shí),它們將顯示在左邊的視圖列表內(nèi):



故事板顯示所有你的視圖控制器的內(nèi)容罗侯。當(dāng)前在你的故事板只有一個(gè)視圖控制器(或場(chǎng)景)器腋,但在本教程的過(guò)程中,您將添加幾個(gè)其他視圖钩杰。

有一個(gè)視圖列表上面的場(chǎng)景稱為Dock:



碼頭顯示場(chǎng)景中的層級(jí)最高的對(duì)象纫塌。 每個(gè)場(chǎng)景至少有一個(gè)視圖控制器對(duì)象,第一響應(yīng)對(duì)象讲弄,和一個(gè)返回的item措左,但它也可能有其他頂級(jí)對(duì)象。碼頭便于連接到接口和方法避除。如果您需要將某物連接到視圖控制器怎披,您可以簡(jiǎn)單地拖動(dòng)到它的圖標(biāo)到Dock。

注意:你可能不會(huì)經(jīng)常使用第一響應(yīng)對(duì)象瓶摆。這是一個(gè)代理對(duì)象凉逛,指的是任何對(duì)象在任何給定的時(shí)間具有第一響應(yīng)狀態(tài)。例如群井,你可以通過(guò)按鈕的觸摸事件成為第一響應(yīng)者:選擇器状飞。如果通過(guò)按壓某一文本框獲得輸入焦點(diǎn),也就是現(xiàn)在的第一響應(yīng)者书斜,將文本粘貼進(jìn)去诬辈。

運(yùn)行這個(gè)應(yīng)用程序,它應(yīng)該與編輯器中設(shè)計(jì)完全相同(可能看起來(lái)不同于下面的截圖-這只是為了演示荐吉,并不會(huì)在以后的教程中使用):



您定義的單視圖控制器被設(shè)置為初始視圖控制器 – 但是應(yīng)用程序怎么加載它? 查看應(yīng)用程序代理方法找到答案焙糟。打開(kāi)AppDelegate.swift文件,你可以看到下面的源代碼:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, >didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}

@UIApplicationMain屬性在AppDelegate類文件的頂部指定為模塊的入口。
使用應(yīng)用程序委托繼承的故事板UIResponder样屠,并具有UIWindow屬性是一項(xiàng)要求酬荞。所有的方法實(shí)際上都是空的搓劫。即使application(_:didFinishLaunchingWithOptions:)簡(jiǎn)單地返回true。
秘密在Info.plist文件中混巧。在項(xiàng)目導(dǎo)航器欄中,點(diǎn)擊Info.plist文件你會(huì)看到:



應(yīng)用程序的故事板用"UIMainStoryboardFile"作為關(guān)鍵字勤揩,亦稱為"Main storyboard file base name"咧党,以指定應(yīng)用程序啟動(dòng)時(shí)必須加載的故事板的名稱。當(dāng)此設(shè)置存在時(shí)陨亡,UIApplication將加載命名的故事板文件傍衡,自動(dòng)從該故事板實(shí)例化“初始視圖控制器”,然后將該控制器的視圖放入一個(gè)新UIWindow對(duì)象负蠕。

您還可以在“常規(guī)選項(xiàng)卡”和“部署信息”部分的“項(xiàng)目設(shè)置”中看到這一點(diǎn):



現(xiàn)在正式創(chuàng)建評(píng)級(jí)程序的幾個(gè)視圖控制器蛙埂。

只需要將其添加到我的選項(xiàng)卡

你要建立的評(píng)級(jí)應(yīng)用程序有一個(gè)帶兩個(gè)屏幕的選項(xiàng)卡界面。使用故事板創(chuàng)建選項(xiàng)卡很容易遮糖。

你將從一個(gè)新的故事板開(kāi)始绣的,所以切換到Main.storyboard文件,刪除之前的視圖控制器欲账。這可以通過(guò)單擊視圖列表中的視圖控制器并按“ Delete”鍵來(lái)完成屡江。

將Tab Bar Controller從對(duì)象庫(kù)拖到畫布中。你可能首先想最大化你的Xcode窗口赛不,因?yàn)門ab Bar控制器附帶兩個(gè)視圖控制器惩嘉,你需要一些操作的空間。 你可以通過(guò)雙擊畫布放大和縮小踢故,也可以通過(guò)按住Ctrl鍵單擊畫布并選擇縮放級(jí)別來(lái)設(shè)置縮放比例文黎。
為了方便起見(jiàn),請(qǐng)?jiān)俅胃哪M器以將場(chǎng)景顯示為iPhone殿较。如前所述耸峭,,在視圖列表中選擇Tab Bar Controller斜脂,在屬性檢查器抓艳,改成4.7英寸的尺寸。這也將改變?cè)诠适掳逯械膬蓚€(gè)嵌入視圖控制器來(lái)模擬iPhone 6或6帚戳。


新的Tab Bar Controller預(yù)先配置兩個(gè)附加的視圖控制器玷或,分別作為標(biāo)簽。UITabBarController是所謂的容器視圖控制器因?yàn)樗粋€(gè)或者多個(gè)其他視圖控制器片任。其他兩個(gè)容器控制器是Navigation Controller和 Split View Controller (稍后您將使用Navigation Controller)偏友。

容器關(guān)系由Tab Bar Controller和它包含的視圖控制器之間的箭頭來(lái)表示。嵌入關(guān)系对供,特別是指圖標(biāo)所看到的箭頭中間的箭頭結(jié)構(gòu)位他。


注意:如果要將Tab Bar Controller及其附屬視圖控制器移動(dòng)為一組氛濒,雙擊縮小,然后你可以按著?鍵并點(diǎn)擊選中拖動(dòng)多個(gè)場(chǎng)景鹅髓∥韪停可以一起移動(dòng)他們。(選定的場(chǎng)景有一個(gè)淡藍(lán)色輪廓窿冯。)

將label拖到第一個(gè)視圖控制器(當(dāng)前標(biāo)題為“ Item 1”)中骗奖,雙擊,設(shè)置文字“First Tab”.也將label拖到第二視圖控制器(“Item2”)中醒串,并設(shè)置文字“Second Tab”.你可以在標(biāo)簽之間切換時(shí)看到實(shí)際發(fā)生的情況执桌。

注意:編輯器縮放時(shí),不能將控件拖到場(chǎng)景中芜赌。您將需要通過(guò)雙擊畫布返回到正常的縮放級(jí)別仰挣。

構(gòu)建并運(yùn)行,你會(huì)在控制臺(tái)看到類似的內(nèi)容:

Ratings[18955:1293100] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?

幸運(yùn)的缠沈,這里的錯(cuò)誤很清楚 - 您從未設(shè)置程序入口膘壶,這意味著你在刪除了前面使用的場(chǎng)景后,沒(méi)有設(shè)置初始視圖控制器博烂。要解決這個(gè)問(wèn)題香椎,選擇Tab Bar Controller找到屬性檢查器。選中Is Initial View Controller單選框禽篱。



在畫布中畜伐,指向已刪除視圖控制器的箭頭現(xiàn)在指向 Tab Bar Controller:



這意味著,當(dāng)你運(yùn)行應(yīng)用程序躺率,程序會(huì)把Tab Bar Controller當(dāng)做主屏幕玛界。
運(yùn)行程序試試看。該應(yīng)用程序現(xiàn)在有一個(gè)tab bar悼吱,您可以在兩個(gè)視圖控制器之間切換選項(xiàng)卡:

提示:要更改初始視圖控制器慎框,還可以在視圖控制器之間拖動(dòng)箭頭。

Xcode實(shí)際上是建立一個(gè)tabbed應(yīng)用程序模板(難怪叫標(biāo)簽應(yīng)用模板)后添,你可以使用笨枯,為了知道他如何很好的工作,你也可以手動(dòng)創(chuàng)建一個(gè)Tab Bar Controller.

注意:如果連接超過(guò)五個(gè)場(chǎng)景的Tab Bar Controller遇西,當(dāng)你運(yùn)行應(yīng)用程序時(shí)會(huì)自動(dòng)獲取更多…選項(xiàng)卡”馅精。相當(dāng)靈巧!

添加一個(gè)Table View Controller

當(dāng)前連接到Tab Bar Controller的兩個(gè)場(chǎng)景都是常規(guī)UIViewController實(shí)例粱檀。你可以用一個(gè)UITableViewController替換第一個(gè)場(chǎng)景洲敢。
單擊選中視圖列表中的第一個(gè)視圖控制器,之后刪除茄蚯。從對(duì)象庫(kù)拖動(dòng)一個(gè)新的Table View Controller 到畫布中以前的場(chǎng)景的位置:



現(xiàn)在压彭,您希望將Table View Controller放置在導(dǎo)航控制器中睦优。選擇Table View Controller,選擇Xcode菜單欄Editor\Embed In\Navigation Controller.這將另一個(gè)控制器添加到畫布中:



您還可以從對(duì)象庫(kù)中拖放導(dǎo)航控制器并嵌入表視圖,但嵌入命令可以比普通拖拽方法節(jié)省時(shí)間壮不。
因?yàn)閷?dǎo)航控制器也是一個(gè)容器視圖控制器(和Tab Bar Controller類似)汗盘,它有一個(gè)關(guān)系箭頭指向表視圖控制器。您也可以在視圖列表中看到這些關(guān)系:

請(qǐng)注意忆畅,嵌入Table View Controller 的控制器給它一個(gè)導(dǎo)航欄衡未。界面生成器自動(dòng)將其放在那里,因?yàn)檫@個(gè)場(chǎng)景現(xiàn)在將顯示在導(dǎo)航控制器的框架內(nèi)家凯。那不是一個(gè)真實(shí)的UINavigationBar 對(duì)象,是一個(gè)模擬的對(duì)象。模擬指標(biāo)將推斷出場(chǎng)景周圍的環(huán)境如失,當(dāng)它位于導(dǎo)航控制器內(nèi)部時(shí)绊诲,當(dāng)它位于Tab Bar控制器內(nèi)時(shí)的選項(xiàng)卡欄等上顯示導(dǎo)航欄。
新的控制器是方形的褪贵。當(dāng)你嵌入他們的Tab Bar Controller掂之,會(huì)在一瞬間,他們將改變他們的模擬大小脆丁,以配合父場(chǎng)景世舰。
要將這兩個(gè)新場(chǎng)景連接到Tab Bar Controller,從Tab Bar Controller拖拽到導(dǎo)航控制器槽卫。放開(kāi)時(shí)跟压,出現(xiàn)一個(gè)小的彈出菜單。選擇Relationship Segue – view controllers 選項(xiàng):



這將在兩個(gè)場(chǎng)景之間創(chuàng)建新的關(guān)系箭頭歼培。這也是一種嵌入關(guān)系震蒋,您可以看到與Tab Bar Controller所包含的其他控制器。
標(biāo)簽欄控制器有兩個(gè)嵌入關(guān)系躲庄,各自是一個(gè)標(biāo)簽查剖。導(dǎo)航控制器本身與Table View Controller有嵌入關(guān)系。
創(chuàng)建此新連接時(shí)噪窘,將在選項(xiàng)卡欄控制器中添加新選項(xiàng)卡,簡(jiǎn)單的命名"item".對(duì)于這個(gè)應(yīng)用程序笋庄,你希望這個(gè)新的場(chǎng)景成為第一個(gè)標(biāo)簽,可以拖動(dòng)選項(xiàng)卡改變他們的位置順序倔监。

運(yùn)行應(yīng)用程序試一下直砂。第一個(gè)選項(xiàng)卡現(xiàn)在包含導(dǎo)航控制器內(nèi)的表視圖。

在添加應(yīng)用程序的一些實(shí)際功能之前丐枉,您需要理清故事板哆键。您將命名第一個(gè)“ Players”標(biāo)簽和第二個(gè)“ Gestures”。您不要在Tab Bar控制器本身上更改此選項(xiàng)瘦锹,應(yīng)該在連接這些選項(xiàng)卡的視圖控制器中進(jìn)行更改籍嘹。
一旦將視圖控制器連接到Tab Bar控制器闪盔,就會(huì)獲得一個(gè)Tab Bar Item對(duì)象,您可以在視圖列表或場(chǎng)景底部看到它辱士。您可以使用此標(biāo)簽欄來(lái)配置標(biāo)簽欄控制器上顯示的標(biāo)題和圖像泪掀。
選擇導(dǎo)航控制器中的標(biāo)簽欄項(xiàng)目,并在屬性檢查器中將其標(biāo)題設(shè)置為"Players":

將視圖控制器的標(biāo)簽欄項(xiàng)目從第二個(gè)選項(xiàng)卡重命名為"Gestures"颂碘,方式相同异赫。

精心設(shè)計(jì)的應(yīng)用程序也應(yīng)該在這些選項(xiàng)卡上放置一些照片。在本教程資源包含子文件夾命名的圖像头岔。將該文件夾拖到項(xiàng)目中的Assets.xcassets子文件夾中塔拳。

返回Main.storyboard文件,在“ 玩家選項(xiàng)卡欄項(xiàng)目的屬性 ”檢查器中峡竣,選擇添加Players.png圖片靠抑。



注意視圖列表中的場(chǎng)景標(biāo)題現(xiàn)在更改為"Players"。

或者适掰,您可以雙擊導(dǎo)航欄并在其中更改標(biāo)題颂碧。請(qǐng)注意,您應(yīng)該雙擊Table View Controller中的模擬導(dǎo)航欄类浪,而不是導(dǎo)航控制器中實(shí)際的導(dǎo)航欄對(duì)象载城。

運(yùn)行應(yīng)用程序,驚嘆標(biāo)簽欄的神奇费就,創(chuàng)建不需要編寫一行代碼诉瓦!


原型Cells

原型單元格允許您直接從故事板編輯器中輕松地為表格視圖單元格設(shè)計(jì)自定義布局。
Table View Controller附帶一個(gè)空白的原型單元格受楼。單擊該單元格以選擇它垦搬,在“ 屬性檢查器”中將“ Style”選項(xiàng)設(shè)置為“ Subtitle”。這會(huì)立即改變單元格的外觀艳汽,以包含兩個(gè)標(biāo)簽猴贰。

在故事板上擁有如此多的可堆疊內(nèi)容,有時(shí)可能難以點(diǎn)擊您想要的內(nèi)容河狐。如果感覺(jué)麻煩米绕,有幾個(gè)選擇。一個(gè)是您可以通過(guò)項(xiàng)目中畫布左側(cè)的“視圖列表”選擇馋艺。第二個(gè)是一個(gè)方便的快捷鍵:按住Ctrl + Shift并點(diǎn)擊你感興趣的區(qū)域栅干。會(huì)彈出窗口,允許您直接通過(guò)光標(biāo)下選擇任何元素捐祠。

如果您之前已經(jīng)使用過(guò)table views碱鳞,并且手動(dòng)創(chuàng)建了自己的單元格,則可以將其視為UITableViewCellStyle.Subtitle樣式踱蛀。使用原型單元格窿给,您可以像您剛才那樣選擇一種內(nèi)置單元格樣式贵白,也可以創(chuàng)建自己的定制設(shè)計(jì)(快速編程)。
將屬性Accessory設(shè)置為Disclosure Indicator崩泡,并設(shè)置Identifierw為PlayerCell禁荒。所有原型單元都應(yīng)具有重用標(biāo)識(shí)符,以便您可以在代碼中引用它們角撞。



運(yùn)行應(yīng)用程序呛伴,沒(méi)有任何改變。這不奇怪:您仍然必須為表添加數(shù)據(jù)源谒所,以便知道要顯示哪些行热康。這正是你接下來(lái)要做的事情。
向項(xiàng)目添加新文件劣领。在iOS / Source下選擇Cocoa Touch Class模板褐隆。將類命名為PlayersViewController并將其設(shè)為UITableViewController的子類。取消選中創(chuàng)建XIB文件剖踊。選擇Swift語(yǔ)言,然后點(diǎn)擊Next衫贬,然后點(diǎn)擊Create德澈。



回到故事板文件并選擇表視圖控制器(確保您選擇實(shí)際的視圖控制器,而不是其中的一個(gè)視圖)固惯。在身份檢查器中梆造,將其類設(shè)置為PlayersViewController。這是通過(guò)您的自定義視圖控制器子類和故事板場(chǎng)景關(guān)聯(lián)的基本步驟葬毫。不要忘記這個(gè)否則你的類不會(huì)被使用镇辉!

從現(xiàn)在開(kāi)始,當(dāng)您運(yùn)行應(yīng)用程序時(shí)贴捡,桌面視圖控制器就是該類的一個(gè)實(shí)例PlayersViewController忽肛。

表視圖應(yīng)顯示players列表,因此現(xiàn)在您將為應(yīng)用程序創(chuàng)建主數(shù)據(jù)模型 - 包含Player對(duì)象的數(shù)組烂斋。使用iOS / Source下的Swift File模板將命名為Player的新文件添加到項(xiàng)目中屹逛。

將Player.swift中的代碼替換為:

import UIKit

struct Player {
var name: String?
var game: String?
var rating: Int

init(name: String?, game: String?, rating: Int) {
self.name = name
self.game = game
self.rating = rating
}
}
這里沒(méi)什么特別的。Player只是這三個(gè)屬性的容器對(duì)象:玩家的名字汛骂,他們正在玩的游戲罕模,以及1到5顆星的等級(jí)。
接下來(lái)帘瞭,您將創(chuàng)建一個(gè)測(cè)試Player對(duì)象數(shù)組淑掌,然后將其賦值給PlayersViewController的一個(gè)數(shù)組。首先使用名為SampleData的Swift File模板創(chuàng)建一個(gè)新文件蝶念。將其添加到SampleData.swift的結(jié)尾:
//Set up sample data

let playersData = [
Player(name:"Bill Evans", game:"Tic-Tac-Toe", rating: 4),
Player(name: "Oscar Peterson", game: "Spin the Bottle", rating: 5),
Player(name: "Dave Brubeck", game: "Texas Hold 'em Poker", rating: 2) ]

在這里抛腕,您定義了一個(gè)名為playersData的常量芋绸,并向其分配了一個(gè)硬編碼的Player對(duì)象數(shù)組。
現(xiàn)在類 PlayersTableViewController: UITableViewController在PlayersViewController.swift中添加一個(gè)Player數(shù)組屬性兽埃,以保存玩家列表:

var players:[Player] = playersData

您可以在定義Player變量時(shí)簡(jiǎn)單地在PlayersViewController中設(shè)置示例數(shù)據(jù)侥钳。但是由于以后可能會(huì)從plist或SQL文件提供此數(shù)據(jù),因此處理視圖控制器外部的數(shù)據(jù)加載是明智之舉柄错。
現(xiàn)在你有一個(gè)充滿Player對(duì)象的數(shù)組舷夺,可以繼續(xù)把數(shù)據(jù)源和PlayersViewController關(guān)聯(lián)起來(lái)。仍然在PlayersViewController.swift中售貌,將表視圖數(shù)據(jù)源方法替換為以下內(nèi)容:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players.count
}

真正的工作發(fā)生在cellForRowAtIndexPath给猾。將此方法替換為當(dāng)前注釋掉的方法:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PlayerCell", forIndexPath: indexPath)

let player = players[indexPath.row] as Player
cell.textLabel?.text = player.name
cell.detailTextLabel?.text = player.game
return cell
}

該方法dequeueReusableCellWithIdentifier(_:forIndexPath:)將檢查是否存在可再重用的單元格。如果沒(méi)有颂跨,它將自動(dòng)分配一個(gè)原型單元格并將其返回給您敢伸。所有您需要做的是在故事板編輯器中提供您在原型單元格上設(shè)置的重用標(biāo)識(shí)符 - 在本例中為PlayerCell。不要忘記設(shè)置該標(biāo)識(shí)符恒削,否則這個(gè)小方案將無(wú)法正常工作池颈!
運(yùn)行應(yīng)用程序,可以看到钓丰,桌面視圖中有玩家躯砰!



使用這些原型單元只需要幾行代碼。我覺(jué)得那真是太棒了携丁。

注意:在這個(gè)應(yīng)用程序中琢歇,您只使用一個(gè)原型單元格,但如果您的表需要顯示不同類型的單元格梦鉴,那么您可以簡(jiǎn)單地向故事板添加其他原型單元格李茫。您可以復(fù)制現(xiàn)有的單元格以創(chuàng)建一個(gè)新單元格,也可以增加Table View的Prototype Cells屬性的值肥橙。確保給每個(gè)單元格一個(gè)重用標(biāo)識(shí)符魄宏。

設(shè)計(jì)您自己的原型單元格

使用標(biāo)準(zhǔn)單元格樣式對(duì)于許多應(yīng)用程序來(lái)說(shuō)都可以,但是對(duì)于這個(gè)應(yīng)用程序快骗,您需要在單元格的右側(cè)添加一個(gè)顯示Player評(píng)級(jí)(一到五顆星)的圖像娜庇。標(biāo)準(zhǔn)單元格樣式不支持該位置中的圖像視圖,因此您必須進(jìn)行自定義設(shè)計(jì)方篮。

切換回Main.storyboard名秀,在表視圖中選擇原型單元格,并在屬性檢查器上將其Style屬性設(shè)置為Custom藕溅。默認(rèn)標(biāo)簽現(xiàn)在消失匕得。

首先使cell高一點(diǎn)。更改“ Size inspector”檢查器中的“ Row Height”值(選擇“ Custom”后)或拖動(dòng)單元格底部的句柄。使cell高60點(diǎn)汁掠。

將兩個(gè)Label對(duì)象從對(duì)象庫(kù)拖動(dòng)到單元格中略吨,并將它們大致放在標(biāo)準(zhǔn)標(biāo)簽之上。只需使用屬性檢查器中的字體和顏色考阱,然后選擇您喜歡的內(nèi)容翠忠。將頂部標(biāo)簽的文本設(shè)置為“ Name”,將底部標(biāo)簽設(shè)置為“ Game”乞榨。

使用Command +單擊選擇視圖列表中的Name和Game標(biāo)簽秽之,然后選擇Editor\Embed In\Stack View.

注意:堆疊視圖在iOS 9中是新的,并且很好地輕松地布局視圖集合吃既。您可以在我們的新書“iOS 9”中了解有關(guān)堆棧視圖的更多信息考榨。

將圖像視圖拖動(dòng)到單元格中,并將其放置在公開(kāi)指示符旁邊的右側(cè)鹦倚。在尺寸檢查器中河质,使其寬81點(diǎn),高35點(diǎn)震叙。將其模式設(shè)置為中心(在“屬性”檢查器中的“查看”下)掀鹅,以便放入此視圖的任何圖像都不會(huì)拉伸。

Command +單擊視圖列表中的堆疊視圖和圖像視圖以選擇它們媒楼。選擇Editor\Embed in\Stack View. Xcode將創(chuàng)建一個(gè)包含這兩個(gè)控件的新的水平堆棧視圖淫半。
選擇此新的水平堆棧視圖,并在屬性檢查器中將對(duì)齊方式更改為中心匣砖,將分布更改為等間距。
現(xiàn)在設(shè)置這個(gè)控件的一些簡(jiǎn)單的自動(dòng)布局昏滴。在故事板的右下角猴鲫,點(diǎn)擊圖標(biāo):



將頂部約束更改為Top:0,Right:20谣殊,Bottom:0和Left:20拂共。確保在值中高亮顯示四個(gè)紅色指針,如圖所示姻几。點(diǎn)擊彈出窗口底部的Add 4 Constraints宜狐。



如果您的堆棧視圖有橙色約束,表明位置約束警告蛇捌。要解決這個(gè)問(wèn)題抚恒,請(qǐng)選擇水平堆棧視圖,然后選擇 Editor\Resolve Auto Layout Issues\Update Frames(在菜單的所選視圖部分)络拌。堆疊視圖定位正確俭驮,橙色約束錯(cuò)誤消失。
要將圖像視圖放置在堆疊視圖中,請(qǐng)選擇視圖列表中的圖像視圖混萝,然后選擇Editor\Resolve Auto Layout Issues\Add Missing Constraints(在菜單的“所選視圖”部分)遗遵。
原型單元的最終設(shè)計(jì)看起來(lái)像這樣:

因?yàn)檫@是一個(gè)專門設(shè)計(jì)的cell,你不能再使用UITableViewCell的textLabel和detailTextLabel屬性來(lái)放置文本標(biāo)簽逸嘀。此單元格不再包含這些屬性標(biāo)簽; 它們僅適用于標(biāo)準(zhǔn)cell類型车要。相反,您將使用tag值來(lái)查找標(biāo)簽崭倘。

為了簡(jiǎn)單起見(jiàn)翼岁,這里使用了tag。在本教程的后面绳姨,您將創(chuàng)建一個(gè)繼承自UITableViewCell的自定義類登澜,并包含與單元格視圖上的標(biāo)簽相對(duì)應(yīng)的屬性。

在“屬性”檢查器中飘庄,將“ Name”標(biāo)簽的tag值設(shè)置為100脑蠕,將“ Game”標(biāo)簽的tag設(shè)置為101,將“ Image View”標(biāo)簽的tag值設(shè)置為102跪削。
然后打開(kāi)PlayersViewController.swift在類的末尾新添加方法imageForRating谴仙,如下所示:

func imageForRating(rating:Int) -> UIImage? {
let imageName = "(rating)Stars"
return UIImage(named: imageName)
}

很簡(jiǎn)單 - 根據(jù)評(píng)分返回不同的星形圖像。仍然在PlayersViewController中碾盐,更改tableView(_:cellForRowAtIndexPath:)方法為以下內(nèi)容:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PlayerCell", forIndexPath: indexPath) //1

let player = players[indexPath.row] as Player //2

if let nameLabel = cell.viewWithTag(100) as? UILabel { //3
nameLabel.text = player.name
}
if let gameLabel = cell.viewWithTag(101) as? UILabel {
gameLabel.text = player.game
}
if let ratingImageView = cell.viewWithTag(102) as? UIImageView {
ratingImageView.image = self.imageForRating(player.rating)
}
return cell
}

以下是您代碼的含義:
1.dequeueReusableCellWithIdentifier將使用重用標(biāo)識(shí)符(PlayerCell如果可用)將現(xiàn)有單元格出隊(duì)晃跺,如果不可用則創(chuàng)建一個(gè)新的標(biāo)識(shí)符。
2.您查找與Player正在填充的行對(duì)應(yīng)的對(duì)象并將其分配player毫玖。
3.標(biāo)簽和圖像由單元格上的標(biāo)簽查找掀虎,并填充player對(duì)象中的數(shù)據(jù)。

應(yīng)該這樣做 現(xiàn)在再次運(yùn)行應(yīng)用程序付枫,可能看起來(lái)像這樣:


嗯烹玉,看起來(lái)不是很正確 - cell似乎被擠壓了。你確實(shí)改變了原型單元格的高度阐滩,但是表格視圖并沒(méi)有考慮到這一點(diǎn)二打。有兩種方法來(lái)解決它:您可以更改表視圖的行高屬性,或?qū)崿F(xiàn)該tableView(tableView:heightForRowAtIndexPath:)方法掂榔。前者在這種情況下很好继效,因?yàn)槲覀冎挥幸环N類型的單元格,我們提前知道高度装获。

注意:tableView(tableView:heightForRowAtIndexPath:)如果您提前不知道單元格的高度瑞信,或者不同的行可能具有不同的高度,才可以使用穴豫。
返回Main.storyboard喧伞,在“ 表視圖” 的“ Size inspector”檢查器中,將行高設(shè)置為60:



再次運(yùn)行應(yīng)用程序,看起來(lái)好多了潘鲫!



順便說(shuō)一下翁逞,如果您通過(guò)拖動(dòng)其句柄而不是鍵入值來(lái)更改單元格的高度,則表視圖的Row Height屬性也會(huì)自動(dòng)更改溉仑。所以這可能是你第一次正常工作挖函。

使用Cell的子類

table view已經(jīng)很好用,但是我不是使用tag值訪問(wèn)原型cell的標(biāo)簽和其他子視圖的大粉絲浊竟。如果您可以將這些標(biāo)簽連接到接口怨喘,然后使用相應(yīng)的屬性,那將會(huì)更加整潔振定。事實(shí)證明必怜,你可以。
使用Cocoa Touch Class模板向項(xiàng)目添加新文件后频。將它命名為PlayerCell并使它繼承自UITableViewCell梳庆。不要選擇創(chuàng)建XIB的選項(xiàng),因?yàn)槟墓适掳逯幸延袉卧瘛?br> 在PlayerCell類中添加這些屬性卑惜,就在類定義的下面:

@IBOutlet weak var gameLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var ratingImageView: UIImageView!

所有這些變量都是IBOutlets,可以連接到故事板中的場(chǎng)景膏执。
將此屬性添加到IBOutlets下方:

var player: Player! {
didSet {
gameLabel.text = player.game
nameLabel.text = player.name
ratingImageView.image = imageForRating(player.rating)
}
}
無(wú)論何時(shí)設(shè)置player屬性,它將使用正確的信息更新IBOutlets露久。
將方法imageForRating(:)從PlayersViewController 移動(dòng)到PlayerCell類更米,以將單元格細(xì)節(jié)保留在同一個(gè)類中。
返回Main.storyboard文件毫痕,選擇原型單元格PlayerCell征峦,并將其類更改為Identity inspector上的“PlayerCell”。現(xiàn)在消请,當(dāng)您向表單查看數(shù)據(jù)源時(shí)dequeueReusableCellWithIdentifier(
:forIndexPath:)眶痰,將返回一個(gè)PlayerCell實(shí)例,而不是常規(guī)的UITableViewCell梯啤。
請(qǐng)注意,您給這個(gè)類與重用標(biāo)識(shí)符相同的名稱 - 它們都稱為PlayerCell - 但這只是因?yàn)槲蚁矚g保持一致存哲。類名稱和重用標(biāo)識(shí)符無(wú)關(guān)因宇,因此您可以按照不同的名稱命名。
現(xiàn)在將標(biāo)簽和圖像視圖連接到這些接口祟偷。導(dǎo)航到故事板中的“ Connections Inspector”察滑,然后從畫布或“視圖列表”中選擇“ Player Cell ”。從“ 連接”檢查器中的nameLabel Outlet拖動(dòng)到“視圖列表”或“畫布” 中的“ Name”標(biāo)簽對(duì)象修肠。為了復(fù)用gameLabel和ratingImageView贺辰。

重要:您應(yīng)該將控件連接到table view cell,而不是view controller!您可以看到饲化,無(wú)論何時(shí)數(shù)據(jù)源通過(guò)dequeueReusableCellWithIdentifier方法向表單視圖提供新的單元格莽鸭,table view 不會(huì)提供實(shí)際的原型單元格,但是可以復(fù)用(或者如果可能的話吃靠,可以回收之前的單元格之一)硫眨。
這意味著PlayerCell在任何給定的時(shí)間將有不止一個(gè)實(shí)例。如果要將label從cell連接到視圖控制器上的接口巢块,則標(biāo)簽的幾個(gè)副本將嘗試使用相同的接口礁阁。這是自找麻煩。(另一方面族奢,將原型單元格連接到視圖控制器上的動(dòng)作完全正常姥闭,如果您UIControls的單元格上有自定義按鈕或其他按鈕,則可以這樣做)越走。

現(xiàn)在你已經(jīng)連接了這些屬性棚品,你可以簡(jiǎn)化數(shù)據(jù)源代碼。在PlayersViewController中弥姻,更改tableView(_:cellForRowAtIndexPath:)為:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PlayerCell", forIndexPath: indexPath)
as! PlayerCell

let player = players[indexPath.row] as Player
cell.player = player
return cell
}

大概是這個(gè)樣子南片。你現(xiàn)在將通過(guò)dequeueReusableCellWithIdentifier方法獲取一個(gè)PlayerCell,然后你可以簡(jiǎn)單地將正確的player傳遞給cell庭敦。在PlayerCell中設(shè)置player變量將自動(dòng)將傳值到標(biāo)簽和圖像視圖中疼进,單元格將使用您在故事板中連接的IBOutlet。使用原型單元格如何使表格視圖不那么麻煩呢秧廉?
運(yùn)行應(yīng)用程序并嘗試伞广。它應(yīng)該仍然像以前一樣,但在幕后疼电,它現(xiàn)在使用您自己的表視圖單元格子類嚼锄!

最后說(shuō)一句.能力一般,水平有限,歡迎指正,有問(wèn)題可以發(fā)郵件到1432103394@qq.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蔽豺,隨后出現(xiàn)的幾起案子区丑,更是在濱河造成了極大的恐慌,老刑警劉巖修陡,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沧侥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡魄鸦,警方通過(guò)查閱死者的電腦和手機(jī)宴杀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拾因,“玉大人旺罢,你說(shuō)我怎么就攤上這事旷余。” “怎么了扁达?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵正卧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我罩驻,道長(zhǎng)穗酥,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任惠遏,我火速辦了婚禮砾跃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘节吮。我一直安慰自己抽高,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布透绩。 她就那樣靜靜地躺著翘骂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帚豪。 梳的紋絲不亂的頭發(fā)上碳竟,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音狸臣,去河邊找鬼莹桅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛烛亦,可吹牛的內(nèi)容都是我干的诈泼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼煤禽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼铐达!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起檬果,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瓮孙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后选脊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杭抠,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年知牌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斤程。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡角寸,死狀恐怖菩混,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扁藕,我是刑警寧澤沮峡,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站亿柑,受9級(jí)特大地震影響邢疙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜望薄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一疟游、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痕支,春花似錦颁虐、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至花嘶,卻和暖如春笋籽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背椭员。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工车海, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拆撼。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓容劳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親闸度。 傳聞我的和親對(duì)象是個(gè)殘疾皇子竭贩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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

  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實(shí)...
    香橙柚子閱讀 23,848評(píng)論 8 183
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)莺禁、插件留量、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,094評(píng)論 4 62
  • 在這個(gè)寡淡了感情的城市 鋼筋水泥筑起的巨大防護(hù)墻隔開(kāi)了友善和暖陽(yáng) 當(dāng)肩膀不能夠給人以依靠 當(dāng)專屬的懷抱開(kāi)始溫暖一個(gè)...
    意莫安閱讀 236評(píng)論 2 1
  • 一聲嘆息吹皺了記憶 泛黃書信舊香四溢 縈繞鼻尖揮之不去的秘密 路燈下的吻禮 輾轉(zhuǎn)千年把愛(ài)恨翻洗 從未細(xì)細(xì)看過(guò)你 尤...
    陌諾流年閱讀 405評(píng)論 15 30
  • 有沒(méi)有人讓你可以無(wú)所顧忌的在他/她面前暢所欲言楼熄,壓根不需要偽裝,不怕出笑話浩峡,不怕被嘲笑可岂?你在他/她面前永遠(yuǎn)都是最真...
    冰山圣羽閱讀 249評(píng)論 0 0