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

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

翻譯自蘋果官網:

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

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

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

學習目標

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

  • 創建第二個 storyboard 場景
  • 理解 table view 的關鍵部分。
  • 創建和設計一個自定義 table view cell(表格視圖單元格)。
  • 理解 table view 的代理和數據源。
  • 使用一個數組來存放和使用數據。
  • 在 table view 中顯示動態數據。

創建開始場景

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

table view 被 UITableViewController 管理,它是 UIViewController 的子類專門用來處理 table view 相關的邏輯。你將會創建一個新的基于它的場景。

添加一個帶 table view 的場景到 storyboard 中
  1. 打開 Main.storyboard。
  2. 在實用工具區中打開對象庫。(或者,選擇 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 并拖動它到畫板中。

現在有兩個場景了,一個用于顯示食物列表,一個是用于添加新的食物。

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

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

    [圖片上傳失敗...(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,在實用工具區打開尺寸檢查器。

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

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

  4. 在尺寸檢查器中,找到名為 Row Heigh 的區域輸入 90。回車確認。

繼續設計單元格界面,稍后將會回來使用這個 table view。

設計自定義 table view 單元格

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

創建 UITableViewCell 的子類
  1. 選擇 File > New > File(或者按 Command-N)。
  2. 在出現的對話框左邊,選擇 iOS 下面的 Source。
  3. 選擇 Cocoa Touch Class,然后點擊 Next。
  4. 在 Class 區域,輸入 Meal。
  5. Subclass Of 區域,選擇 UITableViewCell。
    類的標題自動修改為 MealTableViewCell。從命名很清楚的知道你在創建一個自定義 table view 單元格,所以讓它成為新的名字。
  6. 確保語言選項設置為 Swift 。
  7. 點擊 Next。
    默認保存位置是你的項目目錄。
    Group 選項默認是你的 app 名字,FoodTracker。
    在 Targets 區域,確保你的 app 選中而 targets 不選中。
  8. 讓剩下的使用默認選項,然后點擊 Create。
    Xcode 創建了 MealTableViewCell.swift 文件并定義了 MealTableViewCell 類。

現在,打開 storyboard。
你會注意到 storyboard 中 table view 只顯示了單個單元格。

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

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

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

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

  2. 選中單元格,在實用工具區打開屬性檢查器。

  3. 在屬性檢查器中,找到叫 Identifier 的區域輸入 MealTableViewCell。回車確認。
    這是很重要的一步 - 之后你就知道為什么了。

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

  5. 打開尺寸檢查器。

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

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

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

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

  8. 在識別檢查器中,找到名為 Class 的區域并選擇 MealTableViewCell。

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

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

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

為了達到這個效果,需要一個標簽,一個 image view 和一個評分控件。你可以復用在前一課中創建的評分控件。

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

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

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

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

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

  4. 如果你在前一課沒有添加默認的圖片到你的項目中,現在添加吧。

  5. 選中這個 image view,在實用工具區打開屬性檢查器。

  6. 在屬性檢查器中,找到名為 Image 的區域并選擇 defaultPhoto。

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

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

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

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

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

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

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

  11. 選中這個視圖,在實用工具區打開尺寸檢查器。

  12. 在尺寸檢查器的 Height 區域輸入 44,Width 區域輸入 240。回車確認。

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

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

  14. 選中視圖,打開識別檢查器。

  15. 在識別檢查器中,找到名為 Class 的區域選擇 RatingControl。

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

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

  16. 選中視圖,打開屬性檢查器。

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

我們的界面應該像這樣:

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

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

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

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

現在,使用輔助編輯器預覽界面。

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

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

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

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

    同樣可以收縮大綱視圖。

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

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

    你的 Xcode 窗口應該像這樣:

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

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

注意

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

添加圖片到項目中

下一步,往你的項目中添加示例圖片。當加載初始食物數據到你的 app 時會用到這些圖片。

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

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

    [圖片上傳失敗...(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)]

連接單元格界面和代碼

在單元格顯示動態數據之前,你需要在視圖和單元格的代碼之間創建 outlet 連接。

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

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

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

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

    [圖片上傳失敗...(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. 在出現的對話框中輸入名字:nameLabel。
    忽略剩下的選項。你的對話框應該像這樣:

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

  9. 點擊 Connect。

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

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

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

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

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

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

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

  15. 在出現的對話框中,輸入名字:ratingControl。
    忽略剩下的選項點擊 Connect。

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

MealTableViewCell.swift 中 outlets 應該像這樣:

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

加載初始數據

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

首先,創建一個自定義控制器子類來管理食物列表場景。

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

  2. 在出現的對話框左邊,選擇 iOS 下面的 Source,之后選擇 Cocoa Touch Class。

  3. 點擊 Next。

  4. 在 Class 區域,輸入 Meal。

  5. 在 Subclass of 區域,選擇 UITableViewController。
    類的標題相應修改為 MealTableViewController。就讓它這樣。

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

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

  8. 點擊 Next。

    默認的保存位置是你的項目目錄。
    Group 選項默認是你的 app 名字,FoodTracker。
    在 Target 區域,你的 app 被選中而 tests 未選中。

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

    Xcode 創建 MealTableViewController.swift,一個自定義 table view controller 子類的源代碼文件。

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

加載初始數據
  1. 如果輔助編輯器打開了,點擊 Standard 按鈕返回標準編輯器。

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

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

  2. 打開 MealTableViewController.swift。

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

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

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

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

     func loadSampleMeals() {
     }
    

    這是一個幫助方法用來加載 app 的示例數據。

  5. 在 loadSampleMeals() 方法里面,添加代碼來創建一些 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. 在創建完食物對象后,使用如下代碼添加到 meals 數組中。

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

     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()
     }
    

    當創建 MealTableViewController.swift 時候 Xcode 默認插入一些注釋。本課中不需要它們。

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

     // Load the sample data.
     loadSampleMeals()
    

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

    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 來運行你的項目。編譯應該沒有錯誤。

重要:

如果運行出現編譯問題,確保項目中的圖片名字確實匹配代碼中的名字。

顯示數據

此刻,你的自定義控制器子類, MealTableViewController,有個可變的數組包含一些示例食物。現在你需要在界面上顯示這些真實數據。

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

一個正常工作的 table view 需要三個數據源方法。

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

第一個是 numberOfSectionsInTableView(_:),它告訴 table view 有多少個區域用來顯示。Sections 是 table views 中單元格視覺分組,尤其在 table views 有很多數據時候有用。一個簡單的 table view 例如我們 app 的,僅僅需要顯示單個組,所以 numberOfSectionsInTableView(_:) 數據源方法的實現很簡單。

在 table view 中顯示一個組
  1. 在 MealTableViewController.swift 中,找到 numberOfSectionsInTableView(_:) 數據源方法。模板默認實現如下:

     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 個區域而不是0個。移除 #warning Incomplete implementation 注釋因為你已經完成了實現。

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

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

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

    返回你擁有的食物數量。Array 有個屬性名叫 count 并且返回 array 中對象的數量,所以行的數量是 meals.count。

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

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

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

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

為任何 table view 中給定的行,通過取 Meals 數組中對應的 Meal 對象來配置單元格,使用 Meal 對象的屬性值設置單元格中對應的控件。

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

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

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

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

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

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

    為 storyboard 中設置的標識創建了一個常量。

  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 數組中拿到合適的食物。

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

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

    使用 meal 中對應數據來設置 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 的區域,選擇 MealTableViewController。

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

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

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

準備食物場景用于導航

在 FoddTracker app 中實現導航功能前,需要刪除一些不再需要的代碼和控件。

清理不需要的代碼和控件
  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
    

    稍后會用新的實現來代替它。

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

     @IBOutlet weak var mealNameLabel: UILabel!
    

因為現在項目中兩個視圖控制器了,給 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 區域的 ViewController 為 MealViewController。

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

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

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

注意:

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容