iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Mobile Development

Swift iOS 開發新手村:從入門到 AI 聊天室系列 第 21

Day 21|Xcode 列表入門:資料一覽無遺,實戰 TableView

  • 分享至 

  • xImage
  •  

昨天我們掌握了用 TextField 接收使用者輸入的技巧。但如果想讓使用者發布「多則」留言,並像聊天室一樣顯示出來,該怎麼辦?

這就是 iOS App 中王者級元件—— 列表(TableView) 登場的時刻了!從 Instagram 的動態牆到手機的「設定」選單,TableView 無所不在,是呈現大量、可滑動資料的唯一正解。

今天,我們將透過實作一個簡單的「留言板」,來學習 TableView 的運作核心,並親手打造出你的第一個動態滾動列表!

今日學習重點

  • 自訂 TableViewCell:學習建立自己的 Cell 樣式,並了解其重要性
  • TableView 的三大支柱:深入理解 register(註冊樣板)、dataSource(提供資料)與 delegate(處理互動)的核心分工
  • 實作 dataSource:掌握 numberOfRowsInSectioncellForRowAt 這兩個必備方法,告訴 TableView 要顯示什麼
  • 動態更新列表:學會使用 reloadData(),在資料變動時即時刷新 TableView 的畫面

實作:打造簡易留言板

步驟 1:建立自訂 TableViewCell

我們先建立自訂的 TableViewCell,用來顯示每筆留言。
對專案資料夾按右鍵,選擇 New File from Template...

https://ithelp.ithome.com.tw/upload/images/20251005/20177542ZPdt0zPcpC.png
選擇 Cocoa Touch Class

https://ithelp.ithome.com.tw/upload/images/20251005/20177542WBcDuFBIAF.png
Class 名稱填 MainTableViewCellSubclass of 選擇 UITableViewCell,並勾選 Also create XIB file,確認後按下 Next

https://ithelp.ithome.com.tw/upload/images/20251005/20177542tyRNZ2sWhc.png
確認檔案儲存位置後,按下 Create

https://ithelp.ithome.com.tw/upload/images/20251005/20177542O2JF8ADBQG.png
完成後,會在左側檔案管理看到新增的 MainTableViewCell.swiftMainTableViewCell.xib

自訂 Cell 的用意

TableView 裡,每一列(Row)都是由 Cell 負責呈現。
如果使用系統內建的 Cell,只能顯示簡單的文字或圖片,外觀很死板。
自訂 Cell 可以讓我們:

  • 自由設計版面:想放文字、圖片、按鈕都可以。
  • 重複利用:一次設計好,TableView 會自動重複使用這個模板來產生每一列,節省記憶體。
  • 更好維護:把顯示邏輯和版面設計集中在一個檔案中,後面要改很方便。

這樣我們就能讓留言板的每一筆留言看起來一致又美觀。

步驟 2:設計自訂 Cell 介面

打開 MainTableViewCell.xib,在畫面上放一個 Label,並用 Auto Layout 設定約束(非常重要,避免跑版),建議寬度拉長一點,這樣待會留言的內容才會正確顯示:

https://ithelp.ithome.com.tw/upload/images/20251005/20177542quaxLJxuMT.png
並建立 IBOutlet(從 xib 拉到 swift 檔案中,可參考前面的文章):

@IBOutlet weak var lbText: UILabel!

步驟 3:介面元件與變數連結

回到 MainViewController.xib,放入:

  • 一個 TextField,命名為 txfMessage
  • 一個 Button,命名為 btnEnter
  • 一個 TableView,命名為 tbvMessage

使用 Auto Layout 確保元件位置合適、大小固定。

接著在 MainViewController.swift 中宣告連結跟變數:

@IBOutlet weak var txfMessage: UITextField!
@IBOutlet weak var btnEnter: UIButton!
@IBOutlet weak var tbvMessage: UITableView!

var messages: [String] = []  //儲存留言內容

送出按鈕動作(從 xib 拉到 swift 檔案中,一樣可以參考前面的文章):

@IBAction func didTapButton(_ sender: UIButton) {
    guard let text = txfMessage.text?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty else {
        return
    }
    messages.append(text)
    tbvMessage.reloadData()
    txfMessage.text = ""
    
    // 新增:送出後收起鍵盤
    txfMessage.resignFirstResponder() 
    // 或者用 view.endEditing(true) 也可以
}

步驟 4:設定 TableView 資料來源與代理人

viewDidLoad() 裡設定:

override func viewDidLoad() {
    super.viewDidLoad()
        
    // 讀取我們剛剛做的 MainTableViewCell.xib,讓 TableView 知道要用它來顯示每一列
    let nib = UINib(nibName: "MainTableViewCell", bundle: nil)
    tbvMessage.register(nib, forCellReuseIdentifier: "MainTableViewCell")
        
    // 告訴 TableView,「資料從哪裡來」(DataSource)
    tbvMessage.dataSource = self
    
    // 告訴 TableView,「互動事件誰來處理」(Delegate)
    tbvMessage.delegate = self
}

詳細說明

  • register()
    這一步就像是為你的 Cell 模板辦一張「身分證」,概念是以後只要我喊 MainTableViewCell 這個名字(reuseIdentifier),指的就是這張 Xib 設計圖
  • dataSource(資料來源)
    告訴 TableView
    「我要的資料在哪?一共有幾列?每一列要顯示什麼內容?」
    我們等一下會在 UITableViewDataSource 裡面回答這些問題。
  • delegate(代理人)
    告訴 TableView
    「如果使用者點了某一列,要怎麼反應?」
    例如點擊後印出該留言內容,或跳轉到詳細頁。

小小小結

可以把 TableView 想成一個「清單展示舞台」:
register() → 舞台的布景設計(決定每一列的長相)
dataSource → 送資料的人(負責準備每一列的內容)
delegate → 處理互動的人(負責回應使用者操作)

步驟 5:實作 UITableViewDataSource 與 UITableViewDelegate

這段程式碼是告訴 TableView

  • 要顯示多少列資料
  • 每一列要長什麼樣子、顯示什麼內容
  • 使用者點擊這一列時要做什麼
extension MainViewController: UITableViewDataSource, UITableViewDelegate {
    
    // 1️⃣ 告訴 TableView:一共有幾列資料要顯示
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return messages.count
    }
    
    // 2️⃣ 告訴 TableView:每一列要用什麼 Cell,內容是什麼
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // 從「可重複利用的 Cell 倉庫」取出一個 MainTableViewCell
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell", for: indexPath) as? MainTableViewCell else {
            return UITableViewCell()
        }
        
        // 設定這一列要顯示的文字
        cell.lbText.text = messages[indexPath.row]
        return cell
    }
    
    // 3️⃣ 處理使用者點擊這一列的事件
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("你點了第 \(indexPath.row + 1) 筆留言:\(messages[indexPath.row])")
        
        // 讓點擊效果消失(不會一直反白)
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

重點解釋

  • numberOfRowsInSection
    就像「店裡一共有幾道菜」,這裡是「列表裡有幾筆留言」。
    我們用 messages.count 直接回傳留言數量。
  • cellForRowAt
    就像「每一道菜要怎麼擺盤」,這裡是「每一列要用什麼樣式、顯示什麼文字」。
  • dequeueReusableCell
    這就是拿著「身分證號碼」(withIdentifier)去倉庫領取一個可用的 Cell。如果倉庫裡有閒置的 Cell,系統就直接拿來用;如果沒有,它會用你註冊的模板自動產生一個新的。這個機制大大提升了效能。
  • didSelectRowAt
    處理使用者點擊事件,例如印出留言內容、跳轉到詳細頁。
  • deselectRow
    是讓選中效果消失,不然會一直高亮。

小小小結

你可以把 TableView 想成餐廳點餐流程:
numberOfRowsInSection → 有幾道菜(幾列資料)
cellForRowAt → 每道菜要怎麼上桌(每列怎麼顯示)
didSelectRowAt → 客人點了哪道菜後要做什麼(互動回應)

步驟 6:執行測試

點擊執行按鈕,啟動模擬器,來看看我們的留言板實際效果。
我這裡已經輸入了 20 筆留言,透過上下滑動可以順暢瀏覽所有資料:

https://ithelp.ithome.com.tw/upload/images/20251005/20177542bnRyayXeGp.png
接著,點擊任一筆留言,Xcode 的 Console 會即時印出你點擊的是哪一筆:

https://ithelp.ithome.com.tw/upload/images/20251005/20177542EfLrwt5GAA.png
這樣我們就成功完成了動態列表與點擊互動的功能!

小結一下

太棒了!今天你親手打造了 iOS App 中最重要的元件之一:TableView

我們透過「留言板」的實作,完整走過了 TableView 的生命週期:從設計一個自訂的 Cell,到在 viewDidLoad 中完成三大核心設定(register, dataSource, delegate),最後透過實作 dataSource 的兩個關鍵方法,成功地將資料顯示在畫面上。

你現在不僅理解了 TableView 的運作原理,更學會了如何用 reloadData() 來動態更新列表。這是你從打造靜態畫面,邁向動態資料呈現的關鍵一步!

明日預告

今天的留言板功能很棒,但還有優化的空間!如果想編輯已經發布的留言,而不是只能一直新增,該怎麼做?

明天,我們將為這個專案追加「編輯」功能。你將學會如何偵測使用者點擊了哪一筆留言、將該留言的內容傳回上方的 TextField,並在使用者修改完畢後,更新 TableView 中對應的資料,而不是新增一筆。這將讓你的 App 互動邏輯更完整、更實用!

敬請期待 《Day 22|Xcode 互動進階:點擊編輯留言,動態更新列表》


上一篇
Day 20|Xcode 元件教學:打字也能互動,認識 TextField 輸入框!
系列文
Swift iOS 開發新手村:從入門到 AI 聊天室21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言