今天要介紹的部分,是整個天氣 App 的最後一塊拼圖 —— 自訂的 TableViewCell:SecondTableViewCell
。
這個 Cell 的任務,是在第二個畫面中(SecondViewController
)負責顯示每一個時間段的天氣資料,包括溫度、天氣狀況與舒適度等。
這個畫面的設計主要是以 XIB 完成的。
我們建立一個新的 SecondTableViewCell.xib
,並加上以下元件:
完成後,記得設定 XIB 的 Class 為 SecondTableViewCell
,並建立 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 已經完成了完整流程:
這個 Cell 的實作重點在於「資料解析的結構化」與「介面綁定的清晰性」,
讓每筆氣象資料都能以一致格式呈現,整體架構清楚易懂。