iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
Mobile Development

我將成為Swift之強者系列 第 23

Day23 - 天氣 API 實作:自訂 TableView Cell 顯示天氣資訊

  • 分享至 

  • xImage
  •  

Day23 - 天氣 API 實作:自訂 TableView Cell 顯示天氣資訊

今天要介紹的部分,是整個天氣 App 的最後一塊拼圖 —— 自訂的 TableViewCell:SecondTableViewCell
這個 Cell 的任務,是在第二個畫面中(SecondViewController)負責顯示每一個時間段的天氣資料,包括溫度、天氣狀況與舒適度等。


一、介面設計(XIB)

這個畫面的設計主要是以 XIB 完成的。
我們建立一個新的 SecondTableViewCell.xib,並加上以下元件:

  • 五個 Label:分別顯示「時間」、「天氣狀況」、「最高溫」、「最低溫」、「舒適度」
  • 五個 UIImageView:分別搭配對應的圖示(如太陽、溫度計等)
  • 每個元素透過 Auto Layout 約束好間距與位置,確保在不同螢幕尺寸下都能正常顯示。

完成後,記得設定 XIB 的 ClassSecondTableViewCell,並建立 IBOutlet 連線。


二、程式碼結構

//
//  SecondTableViewCell.swift
//  Weather API
//
//  Created by imac-2156 on 2025/7/30.
//

import UIKit

// 自訂 TableViewCell,用來顯示單一時間段的天氣資料
class SecondTableViewCell: UITableViewCell {

    // MARK: - IBOutlet(UI 元件連接)
    @IBOutlet weak var lbClock: UILabel!       // 顯示時間
    @IBOutlet weak var lbPerson: UILabel!      // 顯示舒適度
    @IBOutlet weak var lbTempHigh: UILabel!    // 顯示最高溫
    @IBOutlet weak var lbTempLow: UILabel!     // 顯示最低溫
    @IBOutlet weak var lbCloud: UILabel!       // 顯示天氣狀況(晴、多雲、雨等)

    // 圖示 UI
    @IBOutlet weak var iconCloud: UIImageView!
    @IBOutlet weak var iconClock: UIImageView!
    @IBOutlet weak var iconPerson: UIImageView!
    @IBOutlet weak var iconTempHigh: UIImageView!
    @IBOutlet weak var iconTempLow: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

三、設定資料:configure() 方法

這是 Cell 最核心的部分,用來接收從 API 回來的天氣資料並顯示。

    func configure(with weatherData: WeatherData, index: Int) {
        guard let location = weatherData.records.location.first else {
            重設標籤()
            return
        }

        func 尋找元素(名稱: String) -> WeatherElement? {
            return location.weatherElement.first { $0.elementName == 名稱 }
        }

        // 天氣狀況(Wx)
        if let wx = 尋找元素(名稱: "Wx")?.time.安全取得(索引: index) {
            lbCloud.text = wx.parameter.parameterName
            lbClock.text = wx.startTime
        } else {
            lbCloud.text = "-"
            lbClock.text = "-"
        }

        // 最低溫(MinT)
        if let minT = 尋找元素(名稱: "MinT")?.time.安全取得(索引: index) {
            lbTempLow.text = "\(minT.parameter.parameterName)°C"
        } else {
            lbTempLow.text = "-"
        }

        // 最高溫(MaxT)
        if let maxT = 尋找元素(名稱: "MaxT")?.time.安全取得(索引: index) {
            lbTempHigh.text = "\(maxT.parameter.parameterName)°C"
        } else {
            lbTempHigh.text = "-"
        }

        // 舒適度(CI)
        if let ci = 尋找元素(名稱: "CI")?.time.安全取得(索引: index) {
            lbPerson.text = ci.parameter.parameterName
        } else {
            lbPerson.text = "-"
        }
    }

這裡的 尋找元素(名稱:) 是個小巧的內部函數,
用來快速根據氣象資料中的名稱(例如 "Wx", "MinT", "MaxT", "CI")找到對應的項目。


四、錯誤處理與安全存取

為了避免因索引越界造成的崩潰,我們額外擴充了陣列安全存取功能:

extension Array {
    func 安全取得(索引: Int) -> Element? {
        return indices.contains(索引) ? self[索引] : nil
    }
}

這樣當資料不足或 API 回傳異常時,就能安全地顯示「-」而不會造成應用程式閃退。


五、重設標籤功能

為了確保當資料載入錯誤時仍有預設畫面:

private func 重設標籤() {
    lbCloud.text = "-"
    lbClock.text = "-"
    lbTempLow.text = "-"
    lbTempHigh.text = "-"
    lbPerson.text = "-"
}

六、小結

到這裡,我們的天氣 App 已經完成了完整流程:

  1. MainViewController — 選擇城市
  2. SecondViewController — 連接 API、解析資料
  3. SecondTableViewCell — 顯示每個時間段的天氣資訊

這個 Cell 的實作重點在於「資料解析的結構化」與「介面綁定的清晰性」,
讓每筆氣象資料都能以一致格式呈現,整體架構清楚易懂。



上一篇
Day22 - 天氣API實作:顯示天氣資料畫面
下一篇
Day24- 天氣 API 實作:XIB及程式碼展示(上)
系列文
我將成為Swift之強者24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言