iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
0
自我挑戰組

iOS 新手開發的大小事系列 第 22

Day 22: [UIKit] UITableView 介紹 -2

  • 分享至 

  • twitterImage
  •  

前情提要

昨天跟今天的內容都是官方網站中,針對 table view 所做的說明跟解釋,因為之前在使用時,對內部的配置並不了解,很多都是自己摸索出來的,在寫鐵人賽時,不斷的翻官方文件,才發現原來文件中都有寫到,就把內容都擷取出來並翻成中文,方便大家閱讀,今天的最後會放上實際 table view 的範例。


使用內置樣式配置單元 (Configure a Cell with a Built-In Style)

配置單元格的最簡單方法是使用 UITableViewCell 提供的內置樣式之一。可以按原樣使用這些樣式;無需提供自定義子類來管理單元。每種樣式都包含一個或兩個標籤,該樣式確定標籤在單元格內容區域中的位置。大多數樣式還在單元格內容的最前沿融合了圖像。若要使用標準樣式之一配置原型單元,請在情節提要中選擇該單元,並將該單元的「樣式」屬性設置為自定義以外的其他值。

tableView(_: cellForRowAt:) 方法中,使用UITableViewCell 的 textLabel,detailTextLabel 和imageView 屬性配置單元格的內容。這些屬性包含視圖,但是如果樣式支持相應的內容,則單元格物件僅分配視圖。例如,基本單元格樣式不支持明細字串,因此該樣式的 detailTextLabel 屬性為 nil。以下範例程式碼顯示瞭如何配置使用基本單元格樣式的單元格。

override func tableView(_ tableView: UITableView, 
             cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   // Reuse or create a cell. 
   let cell = tableView.dequeueReusableCell(withIdentifier: "basicStyle", for: indexPath)

   // For a standard cell, use the UITableViewCell properties.
   cell.textLabel!.text = "Title text"
   cell.imageView!.image = UIImage(named: "bunny")
   return cell
}

使用自定義視圖配置單元 (Configure a Cell with Custom Views)

對於標準樣式以外的外觀,請使用自定義單元格樣式。使用自定義單元格,可以在單元格中指定所需的視圖,它們的配置以及它們的大小和位置。靜態視圖(例如標籤和圖像)是單元格的最佳內容。避免使用需要用戶相互作用的視圖(例如控件)。單元格中不要包括滾動視圖、表視圖、集合視圖或其他複雜的容器視圖。可以在單元格中包括堆棧視圖,但是最小化堆棧視圖中的項目數以提高性能。要配置自定義單元格,請將視圖拖到表的原型單元格中。下圖顯示了具有自定義佈局和其視圖格式的單元格。可以使用約束將視圖放置在單元格內容區域內。設置約束時,請使用「約束到邊距」選項來保留單元格內容區域之間的間隔。

對於自定義單元格,需要定義 UITableViewCell 子類以存取單元格的視圖。將 outlets 添加到子類,並將這些 outlets 連接到原型單元中的相應視圖。

class FoodCell: UITableViewCell {
    @IBOutlet var name : UILabel?
    @IBOutlet var plantDescription : UILabel?
    @IBOutlet var picture : UIImageView?
}

在數據源的 tableView(_: cellForRowAt:) 方法中,使用單元格的 outlets 將值分配給任何視圖。

override func tableView(_ tableView: UITableView, 
             cellForRowAt indexPath: IndexPath) -> UITableViewCell {

   // Reuse or create a cell of the appropriate type.
   let cell = tableView.dequeueReusableCell(withIdentifier: "foodCellType", 
                         for: indexPath) as! FoodCell

   // Fetch the data for the row.
   let theFood = foods[indexPath.row]
        
   // Configure the cell’s contents with data from the fetched object.
   cell.name?.text = theFood.name
   cell.plantDescription?.text = theFood.description
   cell.picture?.image = theFood.picture
        
   return cell
}

更改行高

表格視圖與代表行的單元格分別追蹤行的高度。UITableView 提供了行的預設大小,但是通過為表視圖的屬性 rowHeight 分配自定義值來覆蓋預設高度。當所有行的高度相同時,請始終使用此屬性。這樣做比從委託對象返回高度值更有效。如果行的高度不完全相同,或者可以動態變化,請使用委任物件的 tableView(_: heightForRowAt:) 方法提供高度。實現此方法時,必須為表中的每一行提供值。

以下範例程式碼顯示如何為每個節的第一行返回自定義高度,以及如何為所有其他行使用預設高度。

override func tableView(_ tableView: UITableView, 
           heightForRowAt indexPath: IndexPath) -> CGFloat {
   // Make the first row larger to accommodate a custom cell.
  if indexPath.row == 0 {
      return 80
   }

   // Use the default size for all other rows.
   return UITableView.automaticDimension
}

表格視圖僅要求可見行的高度。當用戶滾動時,表格視圖會要求提供每行顯示時的高度,包括行移出屏幕然後返回屏幕時的高度。


為每一行創建和配置單元格 (Create and Configure Cells for Each Row)

在表格視圖出現在屏幕之前,它要求其數據源物件為表格的可見部分中或附近的行提供單元格。數據源物件的 tableView(_: cellForRowAt:) 方法必須快速響應。通過以下模式實現此方法:

  1. 調用表視圖的 dequeueReusableCell(withIdentifier: for:) 方法以檢索單元格物件。
  2. 使用應用程式的自定義數據配置單元格的視圖。
  3. 將單元格返回到表格視圖。

對於標準單元格樣式,UITableViewCell 包含具有需要配置的視圖的屬性。對於自定義單元格,可以在設計時在視圖中添加視圖,並在 outlets 添加視圖以存取它們。

下面的範例程式碼顯示了配置包含單個文字標籤的單元格的數據源方法的版本。該單元格使用基本樣式,這是標準單元格樣式之一。對於基本樣式的單元格,UITableViewCell 的 textLabel 屬性包含使用數據配置的標籤視圖。

override func tableView(_ tableView: UITableView,
                        cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   // Ask for a cell of the appropriate type.
   let cell = tableView.dequeueReusableCell(withIdentifier: "basicStyleCell", for: indexPath)
        
   // Configure the cell’s contents with the row and section number.
   // The Basic cell style guarantees a label view is present in textLabel.
   cell.textLabel!.text = "Row \(indexPath.row)"
   return cell
}

表格視圖不要求為表格的每一行創建單元格。相反,表視圖並不積極地管理單元格,僅詢問表的可見部分中或附近的那些單元格。延遲創建單元會減少表使用的內存量。但是,這也意味著您的數據源物件必須快速創建單元格。請勿使用 tableView(_: cellForRowAt:) 方法加載表格數據或執行冗長的操作。


實際範例

有兩種方式可以使用 table view,一種是直接在 view controller 上加入 table view,另一種是直接使用 table view controller 取代一開始的 view controller,今天要用方法二來展示。

方法一:

使用方法一時,要記得讓 view controller 採用相關的協定,以及在 viewDidLoad() 中加入相關語法,協定內的方法才會生效。

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// 省略
}
override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.datasource = self
    }

採用 UITableViewDataSource 協定後,會需要實現以下兩種方法:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // put the code here
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // put the code here
    }

方法二:

建立好時,把 Prototype Cells 改為 1

並為 Table View Cell 的 Identifier 命名

此時要建立 table view controller 的 swift 檔,來控制 storyboard 中的 table view controller。

選 New File...

建立一個 Cocoa Touch Class

Subclass 更改為 UITableViewController

在 Storyboard 中將剛新建立的 TableViewController 指定給 UITableViewController

以下是程式碼的部分

class TableViewController: UITableViewController {
 
    var list = ["Hi!", "How", "are", "you"]


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

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

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cellIndentifier = "datacell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIndentifier, for: indexPath)

        cell.textLabel?.text = list[indexPath.row]

        return cell
    }

實際執行


上一篇
Day 21: [UIKit] UITableView 介紹 -1
下一篇
Day 23: [UIKit] UICollectionView 介紹
系列文
iOS 新手開發的大小事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言