馬上著手開發(fā) iOS 應用程序 (八) - 創(chuàng)建表格視圖

重要:這是針對于正在開發(fā)中的API或技術的預備文檔(預發(fā)布版本)洒忧。蘋果提供這份文檔的目的是幫助你按照文中描述的方式對技術的選擇及界面的設計開發(fā)進行規(guī)劃吧雹。這些信息有可能發(fā)生變化宵距,因此根據(jù)本文檔的軟件開發(fā)應當基于最終版本的操作系統(tǒng)和文檔進行測試酸舍。該文檔的新版本或許會隨著API或相關技術未來的發(fā)展而進行更新责嚷。

翻譯自蘋果官網(wǎng):

https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson7.html#//apple_ref/doc/uid/TP40015214-CH8-SW1

在本課中莱睁,創(chuàng)建第二個場景,它基于 table view(表格視圖) 并列出用戶的所有食物颁虐。將會創(chuàng)建自定義表格單元格來顯示每一份食物役耕,最后它應該像這樣:

[圖片上傳失敗...(image-a0b7ee-1608214888461)]

學習目標

在課程的最后,你將能夠:

  • 創(chuàng)建第二個 storyboard 場景
  • 理解 table view 的關鍵部分聪廉。
  • 創(chuàng)建和設計一個自定義 table view cell(表格視圖單元格)瞬痘。
  • 理解 table view 的代理和數(shù)據(jù)源。
  • 使用一個數(shù)組來存放和使用數(shù)據(jù)板熊。
  • 在 table view 中顯示動態(tài)數(shù)據(jù)框全。

創(chuàng)建開始場景

目前,F(xiàn)oddTracker app 有單個被視圖控制器管理的食物場景干签,用戶可以在其中添加和評價食物〗虮纾現(xiàn)在是時候創(chuàng)建新的場景來顯示所有食物的列表。幸運的是容劳,iOS 有個非常強大名叫 table view(UITableView) 的內置類喘沿,它被特別設計用來顯示一個滾動列表。

table view 被 UITableViewController 管理竭贩,它是 UIViewController 的子類專門用來處理 table view 相關的邏輯蚜印。你將會創(chuàng)建一個新的基于它的場景。

添加一個帶 table view 的場景到 storyboard 中
  1. 打開 Main.storyboard留量。
  2. 在實用工具區(qū)中打開對象庫窄赋。(或者,選擇 View > Utilities > Show Object Library楼熄。)
  3. 在對象庫中忆绰,找到 Table View Controller 對象。
  4. 拖動 Table View Controller 放在畫板中食物場景的左邊可岂。
    確保拖動 table view controller 而不是 table view 對象错敢。table view 是被 table view controller 管理的對象,但是需要的是控制器而不是單個 table view缕粹,所以找到 table view controller 并拖動它到畫板中稚茅。

現(xiàn)在有兩個場景了,一個用于顯示食物列表致开,一個是用于添加新的食物峰锁。

讓食物列表成為用戶啟動你的 app 后第一個看到的場景是很有意義的,所以設置 table view controller 作為首要場景告訴 Xcode 你的意圖双戳。

設置 table view controller 作為啟動場景
  1. 如果想要更多空間來工作虹蒋,點擊 Xcode 工具欄中的 Navigator 和 Utilities 按鈕來收縮項目導航和實用工具區(qū)。

    [圖片上傳失敗...(image-dfbe7d-1608214888461)]

  2. 從食物場景中拖動 storyboard entry point 到 table view controller 中飒货。

    [圖片上傳失敗...(image-4209ae-1608214888461)]

    在你的 storyboard 中設置 table view controller 作為啟動視圖控制器魄衅,這讓它在 app 啟動的時候成為第一個加載的場景。

    [圖片上傳失敗...(image-2750a3-1608214888461)]

檢驗:運行你的 app塘辅。取代之前那個擁有文本框晃虫,image view 和評分控件的食物場景,你應該看到一個空的 table view - 它被水平分割線分成一行行但是各行并沒有內容扣墩。

[圖片上傳失敗...(image-402f0d-1608214888461)]

你需要修改 table view 的設置這樣才能在你的 app 中使用哲银。

配置 table view
  1. 在你的 storyboad 中扛吞,打開大綱視圖。

  2. 在大綱視圖中荆责,選擇 Table View滥比。

    table view 嵌套在 Table View Controller Scene > Table View Controller 的下面。你或許要點擊旁邊的三角形才能看到嵌套的 table view做院。

    [圖片上傳失敗...(image-be797c-1608214888461)]

  3. 選中 table view盲泛,在實用工具區(qū)打開尺寸檢查器。

    選中檢查器選擇欄左邊第五個按鈕打開尺寸檢查器键耕。它能讓你編輯 storyboard 中對象的尺寸和位置寺滚。

    [圖片上傳失敗...(image-503b71-1608214888461)]

  4. 在尺寸檢查器中,找到名為 Row Heigh 的區(qū)域輸入 90屈雄〈迨樱回車確認。

繼續(xù)設計單元格界面棚亩,稍后將會回來使用這個 table view蓖议。

設計自定義 table view 單元格

table view 中單獨的一行是由 UITableViewCell 管理的。單元格有不同的預定義的功能以及一些默認的樣式讥蟆。默認的單元格樣式在很多情況下都很棒勒虾,但是在本課中需要在單元格中顯示更多內容,而這超過了默認樣式所允許的了瘸彤,所以需要自定義一個單元格樣式修然。

創(chuàng)建 UITableViewCell 的子類
  1. 選擇 File > New > File(或者按 Command-N)。
  2. 在出現(xiàn)的對話框左邊质况,選擇 iOS 下面的 Source愕宋。
  3. 選擇 Cocoa Touch Class,然后點擊 Next。
  4. 在 Class 區(qū)域结榄,輸入 Meal中贝。
  5. Subclass Of 區(qū)域,選擇 UITableViewCell。
    類的標題自動修改為 MealTableViewCell。從命名很清楚的知道你在創(chuàng)建一個自定義 table view 單元格渠抹,所以讓它成為新的名字。
  6. 確保語言選項設置為 Swift 绣否。
  7. 點擊 Next。
    默認保存位置是你的項目目錄挡毅。
    Group 選項默認是你的 app 名字蒜撮,F(xiàn)oodTracker。
    在 Targets 區(qū)域跪呈,確保你的 app 選中而 targets 不選中段磨。
  8. 讓剩下的使用默認選項取逾,然后點擊 Create。
    Xcode 創(chuàng)建了 MealTableViewCell.swift 文件并定義了 MealTableViewCell 類薇溃。

現(xiàn)在菌赖,打開 storyboard。
你會注意到 storyboard 中 table view 只顯示了單個單元格沐序。

[圖片上傳失敗...(image-9063d7-1608214888461)]

這個單元格代表其他單元格的原型;其中定義的設計和功能會被 table view 的其他單元格使用堕绩。但是首先策幼,需要做一點配置。連接場景中的單元格和剛才創(chuàng)建的自定義單元格子類奴紧。

為 table view 創(chuàng)建一個自定義單元格
  1. 在大綱視圖中特姐,選擇 Table View Cell。
    單元格嵌套在 Table View Controller Scene > Table View Controller > Table View 下面黍氮。你或許需要展開這些對象才能看到單元格唐含。

    [圖片上傳失敗...(image-e1f748-1608214888461)]

  2. 選中單元格,在實用工具區(qū)打開屬性檢查器沫浆。

  3. 在屬性檢查器中捷枯,找到叫 Identifier 的區(qū)域輸入 MealTableViewCell∽ㄖ矗回車確認淮捆。
    這是很重要的一步 - 之后你就知道為什么了。

  4. 在屬性檢查器中本股,找到名為 Selection 的區(qū)域選擇 None攀痊。
    使用這個選項,當用戶點擊單元格的時候不會產生視覺高亮的效果拄显。

  5. 打開尺寸檢查器苟径。

  6. 在尺寸檢查器中,找到名為 Row Height 的區(qū)域輸入 90躬审。
    確保旁邊的 Custom 復選框選中了:

    [圖片上傳失敗...(image-3262a1-1608214888461)]

    回車確認在 storyboard 中顯示了新的單元格高度棘街。

  7. 打開識別(Identity)檢查器。
    回憶下識別檢查器讓你在 storyboard 中編輯一個對象的 Identity(標識) 相關的屬性盒件,例如對象屬于哪個類蹬碧。

  8. 在識別檢查器中,找到名為 Class 的區(qū)域并選擇 MealTableViewCell炒刁。

    [圖片上傳失敗...(image-b5eaeb-1608214888461)]

配置完單元格恩沽,可以在 storyboard 中設計它的自定義界面。它包含食物的名字翔始,照片和評分罗心,應該像這樣:

[圖片上傳失敗...(image-446087-1608214888461)]

為了達到這個效果里伯,需要一個標簽,一個 image view 和一個評分控件渤闷。你可以復用在前一課中創(chuàng)建的評分控件疾瓮。

設計自定義單元格的界面
  1. 選擇 Editor > Canvas > Show Bounds Rectangles 來顯示界面控件的邊界,讓控件在單元格中更容易對齊飒箭。

    [圖片上傳失敗...(image-e2c849-1608214888461)]

  2. 使用對象庫尋找一個 Image View 對象并拖動到單元格中狼电。

  3. 拖動和調整 image view 的尺寸讓它平行并填充單元格的左邊、頂部和底部弦蹂。

    [圖片上傳失敗...(image-a3aff2-1608214888461)]

  4. 如果你在前一課沒有添加默認的圖片到你的項目中肩碟,現(xiàn)在添加吧。

  5. 選中這個 image view凸椿,在實用工具區(qū)打開屬性檢查器削祈。

  6. 在屬性檢查器中,找到名為 Image 的區(qū)域并選擇 defaultPhoto脑漫。

    [圖片上傳失敗...(image-114f6b-1608214888461)]

  7. 使用對象庫來找到一個標簽對象并拖動到單元格中髓抑。

  8. 拖動標簽讓它接近 image view 的右邊并對齊表格單元格的頂部邊界。

    [圖片上傳失敗...(image-6317a8-1608214888461)]

  9. 調整標簽的尺寸讓它的右邊伸展到單元格的右邊緣优幸。

    [圖片上傳失敗...(image-614a94-1608214888461)]

  10. 使用對象庫找到一個 View 對象并拖動到單元格中吨拍。

  11. 選中這個視圖,在實用工具區(qū)打開尺寸檢查器劈伴。

  12. 在尺寸檢查器的 Height 區(qū)域輸入 44密末,Width 區(qū)域輸入 240□髓担回車確認严里。

  13. 拖動視圖讓它在標簽的下面并對齊標簽的左邊緣。

    [圖片上傳失敗...(image-a4711e-1608214888461)]

  14. 選中視圖追城,打開識別檢查器刹碾。

  15. 在識別檢查器中,找到名為 Class 的區(qū)域選擇 RatingControl座柱。

    [圖片上傳失敗...(image-c7b36b-1608214888461)]

    如果你沒有看到 RatingControl 作為彈出菜單的選項迷帜,確保你在畫板(在前一張圖片中顯示了 resize handles 的那個)中選擇了正確的界面控件。

  16. 選中視圖色洞,打開屬性檢查器戏锹。

  17. 在屬性檢查器中,找到名為 Interaction 的區(qū)域并取消選中 User Interaction Enabled 復選框火诸。
    之前設計的自定義評分控件類主要用于交互锦针,但是在單元格中是不需要交互。所以當它在這個環(huán)境中關閉用戶交互,這是很重要的奈搜。

我們的界面應該像這樣:

[圖片上傳失敗...(image-5c5a6e-1608214888461)]

檢驗:運行你的 app悉盆。單元格現(xiàn)在看起來更高了。但是即使你向單元格中添加了所有必須的界面控件馋吗,table view 還是像以前一樣是空的焕盟,為什么會那樣?

[圖片上傳失敗...(image-23e779-1608214888461)]

在一個 storyboard 中宏粤,table view 可以配置用來顯示靜態(tài)的數(shù)據(jù)(storyboard 支持)或者動態(tài)數(shù)據(jù)(table view controller 邏輯支持)脚翘。table view 默認使用動態(tài)數(shù)據(jù),所以你需要在代碼中加載數(shù)據(jù)商架,這正是你希望做的-你僅僅需要實現(xiàn)這個行為堰怨。這意味著你在 storyboard 中提供的靜態(tài)內容并不會在運行時顯示,所以看不到 table view 的內容 - 直到你實現(xiàn)了它之后的數(shù)據(jù)模型蛇摸。

現(xiàn)在,使用輔助編輯器預覽界面灿巧。

預覽界面
  1. 點擊 Xcode 工具欄中的 Assistant 按鈕來打開輔助編輯器赶袄。

    [圖片上傳失敗...(image-c51733-1608214888461)]

  2. 如果想要更多空間來工作,通過點擊 Xcode 工具欄中的 Navigator 和 Utilities 按鈕來收縮項目導航和實用工具區(qū)抠藕。

    [圖片上傳失敗...(image-597a84-1608214888461)]

    同樣可以收縮大綱視圖饿肺。

  3. 在出現(xiàn)的輔助編輯器頂部的編輯器選擇欄中,把輔助編輯器從 Automatic 切換為 Preview > Main.storyboard(Preview)盾似。

    [圖片上傳失敗...(image-faabb2-1608214888461)]

    你的 Xcode 窗口應該像這樣:

    [圖片上傳失敗...(image-591f52-1608214888461)]

預覽界面看起來像預期的那樣敬辣。原型單元格界面看起來完成了。

注意

如果你在界面預覽中看到錯誤的場景了零院,通過點擊場景 dock 確保選擇了 table view 場景溉跃。

添加圖片到項目中

下一步,往你的項目中添加示例圖片告抄。當加載初始食物數(shù)據(jù)到你的 app 時會用到這些圖片撰茎。

你可以在課程最后項目的 Images/ 文件夾中找到示例圖片,或者使用你自己的圖片打洼。(確保使用的圖片的名字匹配稍后的代碼中的圖片名字龄糊。)

添加圖片到項目中
  1. 如果輔助編輯器打開了,點擊 Standard 按鈕返回標準編輯器募疮。
    通過點擊 Xcode 工具欄中的 Navigator 和 Utilities 按鈕打開項目導航和實用工具區(qū)炫惩。

    [圖片上傳失敗...(image-dee0d3-1608214888461)]

  2. 在項目導航中,選擇 Assets.xcassets 來查看 asset catalog阿浓。
    回憶下 asset catalog 是 app 中儲存和組織圖片資源的地方他嚷。

  3. 點擊左下角的加號(+)從彈出菜單中選擇 New Folder。

  4. 雙擊文件夾名字將它重命名為 Sample Images。

  5. 選中文件夾爸舒,點擊左下角的加號(+)按鈕在彈出的菜單中選擇 New Image Set蟋字。

  6. 雙擊圖片集合名字把它重命名為寫代碼時容易記住的名字。

  7. 選擇你電腦中想要添加的圖片扭勉。

  8. 拖動圖片并把它放到圖片集合的 2x 槽中鹊奖。

重復 5-8 操作來盡可能添加你喜歡的圖片。剩下的課程假定你已經有三張不同的圖片了涂炎。

[圖片上傳失敗...(image-df5a8-1608214888461)]

連接單元格界面和代碼

在單元格顯示動態(tài)數(shù)據(jù)之前忠聚,你需要在視圖和單元格的代碼之間創(chuàng)建 outlet 連接。

連接視圖和 MealTableViewCell.swift 代碼
  1. 在你的 storyboard 中唱捣,選擇 table view cell 中的標簽两蟀。

  2. 點擊 Xcode 工具欄中的 Assistant 按鈕來打開輔助編輯器。

    [圖片上傳失敗...(image-828ac7-1608214888461)]

  3. 如果想要更多空間來工作震缭,通過點擊 Xcode 工具欄中的 Navigator 和 Utilities 按鈕來收縮項目導航和實用工具區(qū)赂毯。

    [圖片上傳失敗...(image-497fb-1608214888461)]

  4. 在輔助編輯器頂部的編輯器選擇欄中,將輔助編輯器從 Preview 切換到 Automatic > MealTableViewCell.swift拣宰。

    [圖片上傳失敗...(image-a52c35-1608214888461)]

    MealTableViewCell.swift 顯示在右邊編輯器中党涕。

  5. 在 MealTableViewCell.swift 中,找到 class 行巡社,應該像這樣:

     class MealTableViewCell: UITableViewCell {
    
  6. 在 class 行的下面膛堤,添加如下注釋:

     // MARK: Properties
    
  7. 按住 Control 從畫板中的標簽拖動到右邊編輯器的代碼中,在 MealTableViewCell.swift 中剛添加的注釋的下面停止拖動晌该。

    [圖片上傳失敗...(image-23805e-1608214888461)]

  8. 在出現(xiàn)的對話框中輸入名字:nameLabel肥荔。
    忽略剩下的選項。你的對話框應該像這樣:

    [圖片上傳失敗...(image-303f69-1608214888461)]

  9. 點擊 Connect朝群。

  10. 在你的 storyboard 中燕耿,選擇 table view cell 中的 image view。

  11. 按住 Control 從畫板的 image view 拖動到右邊編輯器的代碼中潜圃,在 MealTableViewCell.swift 的屬性 nameLabel 下面一行停止拖動缸棵。

    [圖片上傳失敗...(image-232790-1608214888461)]

  12. 在出現(xiàn)的對話框中,輸入名字: photoImageView谭期。
    忽略剩下的選項點擊 Connect堵第。
    [圖片上傳失敗...(image-b268a4-1608214888461)]

  13. 在你的 storyboard 中,選擇 table view cell 中的評分控件隧出。

  14. 按住 Control 從畫板的評分控件拖動到顯示在右邊編輯器的代碼中踏志,在 MealTableViewCell.swift 的 photoImageView 屬性的下面一行停止拖動。

    [圖片上傳失敗...(image-b9541c-1608214888461)]

  15. 在出現(xiàn)的對話框中胀瞪,輸入名字:ratingControl针余。
    忽略剩下的選項點擊 Connect饲鄙。

    [圖片上傳失敗...(image-43bee1-1608214888461)]

MealTableViewCell.swift 中 outlets 應該像這樣:

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var ratingControl: RatingControl!

加載初始數(shù)據(jù)

為了在你的單元格中顯示一些真實數(shù)據(jù),你需要編寫代碼來加載數(shù)據(jù)圆雁。此刻忍级,你有個食物的數(shù)據(jù)模型:Meal 類。你同樣需要保存這些食物的列表伪朽。很自然在自定義視圖控制器的子類中保存這些數(shù)據(jù)轴咱。視圖控制器會管理視圖來顯示食物列表,后面會保存一個數(shù)據(jù)模型的引用烈涮。

首先朴肺,創(chuàng)建一個自定義控制器子類來管理食物列表場景。

創(chuàng)建 UITableViewController 的子類
  1. 選擇 File > New > File(或者按 Command-N)坚洽。

  2. 在出現(xiàn)的對話框左邊戈稿,選擇 iOS 下面的 Source,之后選擇 Cocoa Touch Class讶舰。

  3. 點擊 Next鞍盗。

  4. 在 Class 區(qū)域,輸入 Meal跳昼。

  5. 在 Subclass of 區(qū)域橡疼,選擇 UITableViewController。
    類的標題相應修改為 MealTableViewController庐舟。就讓它這樣。

  6. 確保 Also Create XIB file 選項沒有選中住拭。

  7. 確保語言選項設置成了 Swift挪略。

  8. 點擊 Next。

    默認的保存位置是你的項目目錄滔岳。
    Group 選項默認是你的 app 名字杠娱,F(xiàn)oodTracker。
    在 Target 區(qū)域谱煤,你的 app 被選中而 tests 未選中摊求。

  9. 剩下都是默認值,然后點擊 Create刘离。

    Xcode 創(chuàng)建 MealTableViewController.swift室叉,一個自定義 table view controller 子類的源代碼文件。

在自定義子類中硫惕,定義一個屬性來存儲 Meal 對象的列表茧痕。Swift 標準庫包含一個叫 Array 的數(shù)據(jù)結構非常適合記錄這種列表。

加載初始數(shù)據(jù)
  1. 如果輔助編輯器打開了恼除,點擊 Standard 按鈕返回標準編輯器踪旷。

    點擊 Xcode 工具欄中的 Navigator 和 Utilities 按鈕展開項目導航和實用工具區(qū)。

    [圖片上傳失敗...(image-ce4aa9-1608214888461)]

  2. 打開 MealTableViewController.swift。

  3. 在 MealTableViewController.swift 的 class 行下面令野,添加如下代碼:

     // MARK: Properties
    
     var meals = [Meal]()
    

    代碼定義了 MealTableViewController 的一個屬性并將它初始化默認的值(一個空的食物對象數(shù)組)舀患。通過設置 meals 為一個變量而不是常量,讓數(shù)組可變化气破,這意味著你可以在初始化它之后添加對象聊浅。

  4. 在 MealTableViewController.swift 文件的 viewDidLoad() 方法的后面,添加如下方法:

     func loadSampleMeals() {
     }
    

    這是一個幫助方法用來加載 app 的示例數(shù)據(jù)堵幽。

  5. 在 loadSampleMeals() 方法里面狗超,添加代碼來創(chuàng)建一些 Meal 對象。你可以憑著自己喜歡來給這些示例食物命名和設置評分朴下,當然努咐,這里是一些例子:

     let photo1 = UIImage(named: "meal1")!
     let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4)!
      
     let photo2 = UIImage(named: "meal2")!
     let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5)!
      
     let photo3 = UIImage(named: "meal3")!
     let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3)!
    

確保項目中圖片名字匹配你在代碼中寫的名字。

  1. 在創(chuàng)建完食物對象后殴胧,使用如下代碼添加到 meals 數(shù)組中渗稍。

     meals += [meal1, meal2, meal3]
    
  2. 找到 viewDidLoad() 方法。默認模板實現(xiàn)如下:

     override func viewDidLoad() {
         super.viewDidLoad()
         
         // Uncomment the following line to preserve selection between presentations
         // self.clearsSelectionOnViewWillAppear = false
         
         // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
         // self.navigationItem.rightBarButtonItem = self.editButtonItem()
     }
    

    當創(chuàng)建 MealTableViewController.swift 時候 Xcode 默認插入一些注釋团滥。本課中不需要它們竿屹。

  3. 在 viewDidLoad() 方法中,刪除注釋并替換為這些代碼用來在 super.viewDidLoad() 后面來加載示例食物數(shù)據(jù):

     // Load the sample data.
     loadSampleMeals()
    

    調用剛才添加的幫助方法用來當視圖加載的時候加載數(shù)據(jù)灸姊。你分割功能到定義的方法來讓代碼更模塊化和可讀拱燃。

    viewDidLoad() 方法應該像這樣:

     override func viewDidLoad() {
         super.viewDidLoad()
         
         // Load the sample data.
         loadSampleMeals()
     }
    

    loadSampleMeals() 方法應該像這樣:

     func loadSampleMeals() {
         let photo1 = UIImage(named: "meal1")!
         let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4)!
         
         let photo2 = UIImage(named: "meal2")!
         let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5)!
         
         let photo3 = UIImage(named: "meal3")!
         let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3)!
         
         meals += [meal1, meal2, meal3]
     }
    

檢驗:通過選擇 Product > Build 來運行你的項目。編譯應該沒有錯誤力惯。

重要:

如果運行出現(xiàn)編譯問題碗誉,確保項目中的圖片名字確實匹配代碼中的名字。

顯示數(shù)據(jù)

此刻父晶,你的自定義控制器子類哮缺, MealTableViewController,有個可變的數(shù)組包含一些示例食物〖缀龋現(xiàn)在你需要在界面上顯示這些真實數(shù)據(jù)尝苇。

為了顯示動態(tài)數(shù)據(jù),table view 需要兩個很重要的幫手:數(shù)據(jù)源和代理埠胖。數(shù)據(jù)源糠溜,就像名字說的,提供給 table view 需要顯示的數(shù)據(jù)押袍。代理幫助 table view 管理單元格選中诵冒、行高度和其他顯示數(shù)據(jù)相關功能。UITableViewController 和它的子類默認遵循了必要的協(xié)議來讓它既是一個數(shù)據(jù)源(UITableViewDataSource 協(xié)議)又是一個代理(UITableViewDelegate)谊惭。你的工作就是在 table view controller 中實現(xiàn)合適的協(xié)議方法這樣 table view 才能有正確的功能汽馋。

一個正常工作的 table view 需要三個數(shù)據(jù)源方法侮东。

    func numberOfSectionsInTableView(tableView: UITableView) -> Int
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

第一個是 numberOfSectionsInTableView(_:),它告訴 table view 有多少個區(qū)域用來顯示豹芯。Sections 是 table views 中單元格視覺分組悄雅,尤其在 table views 有很多數(shù)據(jù)時候有用。一個簡單的 table view 例如我們 app 的铁蹈,僅僅需要顯示單個組宽闲,所以 numberOfSectionsInTableView(_:) 數(shù)據(jù)源方法的實現(xiàn)很簡單。

在 table view 中顯示一個組
  1. 在 MealTableViewController.swift 中握牧,找到 numberOfSectionsInTableView(_:) 數(shù)據(jù)源方法容诬。模板默認實現(xiàn)如下:

     override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
         // #warning Incomplete implementation, return the number of sections
         return 0
     } 
    
  2. 從0修改返回值為1,并且刪除警告注釋沿腰。

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

    代碼讓 table view 顯示 1 個區(qū)域而不是0個览徒。移除 #warning Incomplete implementation 注釋因為你已經完成了實現(xiàn)。

下一個數(shù)據(jù)源方法颂龙, tableView(_:numberOfRowsInSection:) 告訴 table view 在一個給定組中顯示多少行习蓬。每份食物應該在組中有屬于它自己的行,這意味著行的數(shù)量應該等于 meals 數(shù)組中 Meal 對象的數(shù)量措嵌。

返回 table view 中行的數(shù)量
  1. 在 MealTableViewController.swift 中躲叼,找到 tableView(_:numberOfRowsInSection:) 數(shù)據(jù)源方法。模板默認實現(xiàn)如下:

     override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         // #warning Incomplete implementation, return the number of rows
         return 0
     }
    

    返回你擁有的食物數(shù)量企巢。Array 有個屬性名叫 count 并且返回 array 中對象的數(shù)量枫慷,所以行的數(shù)量是 meals.count。

  2. 修改 tableView(_:numberOfRowsInSection:) 數(shù)據(jù)源方法來返回合適行的數(shù)量浪规,移除警告注釋流礁。

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

最后的數(shù)據(jù)源方法,tableView(_:cellForRowAtIndexPath:)罗丰,配置單元格來顯示給定的行數(shù)據(jù)。table view 的每一行對應一個單元格再姑,那個單元格決定行中顯示的內容以及怎么布局萌抵。

當 table views 有很少行的時候,所有的行或許同時都顯示在屏幕上元镀,所以為 table view 的每一行調用這個方法绍填。但是當 table views 有很多行,同時只能顯示所有中的一小部分栖疑。只為正在顯示的行請求數(shù)據(jù)是很有效率的讨永,那正是 tableView(_:cellForRowAtIndexPath:) 允許 table view 做的。

為任何 table view 中給定的行遇革,通過取 Meals 數(shù)組中對應的 Meal 對象來配置單元格卿闹,使用 Meal 對象的屬性值設置單元格中對應的控件揭糕。

在 table view 中配置和顯示單元格
  1. 在 MealTableViewController.swift 中,找到并取消 tableView(_:cellForRowAtIndexPath:) 數(shù)據(jù)源方法的注釋锻霎。(為了取消方法的注釋著角,移除環(huán)繞它的 /* 和 */ 字符。)
    當你做了這些旋恼,模板默認實現(xiàn)如下:

     override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
         
         // Configure the cell...
         
         return cell
     }
    

方法執(zhí)行一些操作吏口。首先通過占位符標識向 table view 請求一個單元格,添加一個注釋表示在這里配置單元格冰更,之后返回單元格产徊。

為了讓代碼工作,修改占位符標識為之前你在原型單元格中設置的(MealTableViewCell)蜀细,之后添加代碼來配置單元格舟铜。

  1. 在方法的開始添加代碼:

     // Table view cells are reused and should be dequeued using a cell identifier.
     let cellIdentifier = "MealTableViewCell"
    

    為 storyboard 中設置的標識創(chuàng)建了一個常量。

  2. 更新占位符標識為 storyboard 中設置的標識审葬。方法第二行代碼應該像這樣:

     let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
    
  3. 因為使用了自定義的單元格類深滚,強轉單元格類型為你自定義單元格子類,MealTableViewCell涣觉,方法代碼的第二行改成這樣:

     let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MealTableViewCell
    
  4. 之后添加如下代碼:

     // Fetches the appropriate meal for the data source layout.
     let meal = meals[indexPath.row]
    

    代碼從 meals 數(shù)組中拿到合適的食物痴荐。

  5. 刪除 // Configure the cell 注釋并在這個地方添加代碼:

     cell.nameLabel.text = meal.name
     cell.photoImageView.image = meal.photo
     cell.ratingControl.rating = meal.rating 
    

    使用 meal 中對應數(shù)據(jù)來設置 table view 單元格的每個視圖。

tableView(_:cellForRowAtIndexPath:) 方法應該像這樣:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        // Table view cells are reused and should be dequeued using a cell identifier.
        let cellIdentifier = "MealTableViewCell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MealTableViewCell
        
        // Fetches the appropriate meal for the data source layout.
        let meal = meals[indexPath.row]
        
        cell.nameLabel.text = meal.name
        cell.photoImageView.image = meal.photo
        cell.ratingControl.rating = meal.rating
        
        return cell
    }

最后一步就是連接 MealTableViewController.swift 中定義的代碼和 storyboard 的場景官册。

指向控制器到 MealTableViewController.swift
  1. 打開你的 storyboard生兆。

  2. 點擊場景 dock 選擇 table view 控制器,可以看到它周圍有個藍色的框膝宁。

  3. 打開識別檢查器鸦难。

  4. 在識別檢查器中,找到名為 Class 的區(qū)域员淫,選擇 MealTableViewController合蔽。

    [圖片上傳失敗...(image-4a89fa-1608214888461)]

檢驗:運行 app。在 viewDidLoad() 方法中添加的列表項應該顯示在 table view 中作為單元格介返。你會注意到 table view 單元格和狀態(tài)欄之間有一點重疊 - 在下一課會修復它的拴事。

[圖片上傳失敗...(image-85ded9-1608214888461)]

準備食物場景用于導航

在 FoddTracker app 中實現(xiàn)導航功能前,需要刪除一些不再需要的代碼和控件圣蝎。

清理不需要的代碼和控件
  1. 打開 storyboard 查看食物場景刃宵。

    你的食物場景界面應該像這樣:

    [圖片上傳失敗...(image-429f7c-1608214888461)]

  2. 在食物場景中,選擇 Meal Name 標簽徘公,按 Delete 鍵刪除它牲证。

    堆棧視圖會合理調整剩余的控件位置。

    [圖片上傳失敗...(image-3883f7-1608214888461)]

  3. 打開 ViewController.swift关面。

  4. 在 ViewController.swift 中坦袍,找到 textFieldDidEndEditing(_:) 方法十厢。

     func textFieldDidEndEditing(textField: UITextField) {
         mealNameLabel.text = textField.text
     }
    
  5. 刪除設置標簽文本屬性那行。

     mealNameLabel.text = textField.text
    

    稍后會用新的實現(xiàn)來代替它键闺。

  6. 在 ViewController.swift 中寿烟,找到 mealNameLabel outlet 并刪除它。

     @IBOutlet weak var mealNameLabel: UILabel!
    

因為現(xiàn)在項目中兩個視圖控制器了辛燥,給 ViewController.swift 一個更有意義的名字吧筛武。

重命名 ViewController.swift 文件
  1. 在項目導航中,點擊 ViewController.swift 文件并按回車鍵挎塌。
    Xcode 讓你為文件輸入新的名字徘六。

  2. 重命名文件為 MealViewController.swift,回車確認榴都。

  3. 在 MealViewController.swift 中待锈,找到類定義行:

     class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
  4. 修改類的名字為 MealViewController。

     class MealViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
  5. 文件頂部的注釋嘴高,同樣從 ViewController.swift 修改為 MealViewController.swift竿音。

  6. 打開 storyboard。

  7. 點擊場景 dock 選中食物場景拴驮。

    [圖片上傳失敗...(image-4deb88-1608214888461)]

  8. 打開識別(Identity)檢查器春瞬。

  9. 在識別檢查器中,修改 Class 區(qū)域的 ViewController 為 MealViewController套啤。

    [圖片上傳失敗...(image-c80217-1608214888461)]

檢驗:編譯運行你的 app宽气。一切都和之前一樣。

你或許看到一個 Xcode 警告說明無法訪問 app 中的食物場景潜沦。不要擔心萄涯,會在下一課添加導航行為。

注意:

為了看到本課的完整示例項目唆鸡,下載文件并在 Xcode 中查看它涝影。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市争占,隨后出現(xiàn)的幾起案子袄琳,更是在濱河造成了極大的恐慌,老刑警劉巖燃乍,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宛琅,居然都是意外死亡刻蟹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門嘿辟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舆瘪,“玉大人片效,你說我怎么就攤上這事∮⒐牛” “怎么了淀衣?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長召调。 經常有香客問我膨桥,道長,這世上最難降的妖魔是什么唠叛? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任只嚣,我火速辦了婚禮,結果婚禮上艺沼,老公的妹妹穿的比我還像新娘册舞。我一直安慰自己,他們只是感情好障般,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布调鲸。 她就那樣靜靜地躺著,像睡著了一般挽荡。 火紅的嫁衣襯著肌膚如雪藐石。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天徐伐,我揣著相機與錄音贯钩,去河邊找鬼。 笑死办素,一個胖子當著我的面吹牛角雷,可吹牛的內容都是我干的。 我是一名探鬼主播性穿,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼勺三,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了需曾?” 一聲冷哼從身側響起吗坚,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呆万,沒想到半個月后商源,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡谋减,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年牡彻,在試婚紗的時候發(fā)現(xiàn)自己被綠了扎附。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轻猖。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出钦讳,到底是詐尸還是另有隱情念颈,我是刑警寧澤谤草,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布犹褒,位于F島的核電站,受9級特大地震影響渐行,放射性物質發(fā)生泄漏轰坊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一殊轴、第九天 我趴在偏房一處隱蔽的房頂上張望衰倦。 院中可真熱鬧,春花似錦旁理、人聲如沸樊零。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驻襟。三九已至,卻和暖如春芋哭,著一層夾襖步出監(jiān)牢的瞬間沉衣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工减牺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留豌习,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓拔疚,卻偏偏與公主長得像肥隆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稚失,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容