我們今天要利用中央氣象局的 API 來取得該地區的天氣資料,並顯示在畫面上。
在程式開頭,我們宣告兩個變數:
var selectedArea: String?
var weatherData2: weatherData?
接著在 viewDidLoad()
中設定 TableView
與初始顯示內容。
override func viewDidLoad() {
super.viewDidLoad()
tbvWeather.delegate = self
tbvWeather.dataSource = self
tbvWeather.register(UINib(nibName: "SecondTableViewCell", bundle: nil), forCellReuseIdentifier: "SecondTableViewCell")
lbCt.text = selectedArea
callAPI()
}
在這個畫面中,我們也會設計一個返回按鈕,讓使用者可以回到選擇城市的畫面:
@IBAction func btnData2Tapped(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
在查詢氣象局 API 時,因為網址中會包含中文字(像是「臺北市」),
所以我們要先進行編碼處理,讓網址成為能用的 URL。
// 定義一個func叫LegitimateURL,並給定參數是原本的URL,並返回url的物件
func LegitimateURL(requestURL: String) -> URL {
let legitimateURL = requestURL.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
//創建一個url,並強制解包legitimateURL,代表legitimateURL不能為空值
let url = URL.init(string: legitimateURL!)
return url!
}
使用 URLSession
來取得天氣資料:
func callAPI() {
// 這邊強制解包剛剛選取的selectedArea
let city = "\(selectedArea!)"
let requestURL = LegitimateURL(requestURL: "https://opendata.cwa.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=CWA-AC274CA4-6BF4-4840-BCA4-DF4B3B8449F5&locationName=" + city)
//這邊是用URLSession.shared.dataTask發送請求,這是一個異步處理喔,這邊的self是防止閉包的循環引用的問題
URLSession.shared.dataTask(with: requestURL) { [self] (data, response, error) in
//錯誤處理,如請求失敗則返回錯誤訊息
if let error = error {
print(error.localizedDescription)
}
//將response轉換為HTTPURLResponse,並 print出HTTPURLResponse
if let response = response {
print("====================")
print(response as! HTTPURLResponse)
print("====================")
}
if let data = data {
let decoder = JSONDecoder()
do {
self.weatherData2 = try decoder.decode(weatherData.self, from: data)
print("====================")
print(weatherData2 ?? "")
print("====================")
//主線成
DispatchQueue.main.async {
self.tbvWeather.reloadData()
}
} catch {
print(error.localizedDescription)
}
}
}.resume()
}
}
我們要讓 TableView
正確顯示每個時段的天氣資料:
extension SecondViewController {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// 根據 weatherData2 決定 cell 數量
return weatherData2?.records.location[0].weatherElement[0].time.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SecondTableViewCell", for: indexPath) as! SecondTableViewCell
if let weatherData = weatherData2 {
cell.configure(with: weatherData, index: indexPath.row)
}
return cell
}
func setupTableViewFrame() {
tbvWeather.frame = CGRect(x: 10, y: 80, width: self.view.frame.width - 20, height: self.view.frame.height - 160)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200 // 你可以依需求調整高度
}
}
我們今天成功讓API的資料可以顯示在畫面上。
這30天裡,我從一開始對這門程式語言完全不熟悉,到能一步步完成一個又一個專案。雖然還有許多地方需要磨練,但這段學習旅程的經驗,肯定會讓我的人生更加豐富。