最後一天来把天气 App 的剩余部分给完成,冲啊!
当一开始进入 App 会直接显示宜兰县在第一个时间区间的天气资讯。
点击一下画面可以选择地点,因此要把选取器放入提示框里。
选完地点後接着就让使用者选择时间。
完整的程序码如下,看起来有点恐怖,但如果清楚流程其实还好。
import UIKit
class ViewController: UIViewController {
let location = ["宜兰县","花莲县","台东县","澎湖县","金门县","连江县","台北市","新北市","桃园市","台中市","台南市","高雄市","基隆市","新竹县","新竹市","苗栗县","彰化县","南投县","云林县","嘉义县","嘉义市","屏东县"]
var selectLocation = "宜兰县" // 选取器选择的地点
var selectTime = 0 // 选取器选择的时间区间,范围 0~2
var timeData = ["","",""] // 读取 JSON 後,存放三个时间的 startTime
let locationPickerView = UIPickerView(frame: CGRect(x: 0, y: 50, width: 270, height: 150)) // 把地点选取器放入提示框里,大小要自己尝试调整
let timePickerView = UIPickerView(frame: CGRect(x: 0, y: 50, width: 270, height: 150)) // 把时间选取器放入提示框里,大小要自己尝试调整
@IBOutlet weak var locationName: UILabel!
@IBOutlet weak var Wx: UILabel!
@IBOutlet weak var PoP: UILabel!
@IBOutlet weak var MinT: UILabel!
@IBOutlet weak var CI: UILabel!
@IBOutlet weak var MaxT: UILabel!
@IBOutlet weak var startTime: UILabel!
@IBOutlet weak var endTime: UILabel!
@IBOutlet weak var weatherIcon: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
locationPickerView.dataSource = self
locationPickerView.delegate = self
timePickerView.dataSource = self
timePickerView.delegate = self
loadJSON(locationName: selectLocation, time: selectTime) // 进入画面前先读一次 JSON,以便得到 timeData
}
// MARK:- 读 JSON 资料,必须要传入地点和时间
func loadJSON(locationName: String ,time: Int){
let url = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=CWB-6F803E34-66E5-4135-AC7D-25811AD53D5C&format=JSON&locationName=\(locationName)"
let newUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! // 网址有中文,需要先编码
var request = URLRequest(url: URL(string: newUrl)!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request){(data, respond, error) in
let decoder = JSONDecoder()
if let data = data, let weather = try? decoder.decode(Weather.self, from: data){
print(weather)
DispatchQueue.main.sync {
self.locationName.text = weather.records.location[0].locationName
self.Wx.text = weather.records.location[0].weatherElement[0].time[time].parameter.parameterName
self.PoP.text = weather.records.location[0].weatherElement[1].time[time].parameter.parameterName + "%"
self.MinT.text = weather.records.location[0].weatherElement[2].time[time].parameter.parameterName + "°" + weather.records.location[0].weatherElement[2].time[time].parameter.parameterUnit!
self.CI.text = weather.records.location[0].weatherElement[3].time[time].parameter.parameterName
self.MaxT.text = weather.records.location[0].weatherElement[4].time[time].parameter.parameterName + "°" + weather.records.location[0].weatherElement[4].time[time].parameter.parameterUnit!
self.startTime.text = weather.records.location[0].weatherElement[0].time[time].startTime
self.endTime.text = weather.records.location[0].weatherElement[0].time[time].endTime
for i in 0...2 {
self.timeData[i] = weather.records.location[0].weatherElement[0].time[i].startTime
} // 把三个 startTime 放入阵列
self.changeWeatherIcon() // 根据天气现象改变图示
}
}
else {
print("error")
}
}
task.resume()
}
// MARK:- 改变 weatherIcon
func changeWeatherIcon() {
if Wx.text!.contains("积冰") {
weatherIcon.image = UIImage.init(systemName: "snow")
}
else if Wx.text!.contains("暴风雪"){
weatherIcon.image = UIImage.init(systemName: "wind.snow")
}
else if Wx.text!.contains("雪") {
if Wx.text!.contains("雨") {
weatherIcon.image = UIImage.init(systemName: "cloud.sleet")
}
else {
weatherIcon.image = UIImage.init(systemName: "cloud.snow")
}
}
else if Wx.text!.contains("雨") {
if Wx.text!.contains("雷") {
weatherIcon.image = UIImage.init(systemName: "cloud.bolt.rain")
}
else if Wx.text!.contains("晴"){
weatherIcon.image = UIImage.init(systemName: "cloud.sun.rain")
}
else {
weatherIcon.image = UIImage.init(systemName: "cloud.rain")
}
}
else if Wx.text!.contains("晴") {
if Wx.text!.contains("云") {
weatherIcon.image = UIImage.init(systemName: "cloud.sun")
}
else {
weatherIcon.image = UIImage.init(systemName: "sun.max")
}
}
else if Wx.text!.contains("阴") {
weatherIcon.image = UIImage.init(systemName: "smoke.fill")
}
else if Wx.text!.contains("云") {
weatherIcon.image = UIImage.init(systemName: "smoke")
}
}
// MARK:- 点击一下画面依序跳出选取器
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
locationView() // 点击一下画面可以选择地点
}
func locationView() {
let alertView = UIAlertController(
title: "选择地点",
message: "\n\n\n\n\n\n\n\n\n", // 因为要放入选取器,使提示框高度增高
preferredStyle: .alert
)
let cancelAction = UIAlertAction(
title: "取消",
style: .default,
handler: nil
)
let okAction = UIAlertAction(
title: "确认",
style: .destructive,
handler: {_ in
self.loadJSON(locationName: self.selectLocation, time: self.selectTime)
self.timeView()} // 选完地点接着选时间
)
alertView.view.addSubview(locationPickerView)
alertView.addAction(cancelAction)
alertView.addAction(okAction)
present(alertView, animated: true, completion: nil)
}
func timeView() {
let alertView = UIAlertController(
title: "选择时间",
message: "\n\n\n\n\n\n\n\n\n", // 因为要放入选取器,使提示框高度增高
preferredStyle: .alert
)
let cancelAction = UIAlertAction(
title: "取消",
style: .default,
handler: nil
)
let okAction = UIAlertAction(
title: "确认",
style: .destructive,
handler: {_ in self.loadJSON(locationName: self.selectLocation, time: self.selectTime)}
)
alertView.view.addSubview(timePickerView)
alertView.addAction(cancelAction)
alertView.addAction(okAction)
present(alertView, animated: true, completion: nil)
}
}
// MARK:- 选取器
extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == locationPickerView {
return location.count
}
if pickerView == timePickerView {
return timeData.count // 三个时间区间
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == locationPickerView {
return location[row]
}
if pickerView == timePickerView {
return timeData[row]
}
return nil
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == locationPickerView {
selectLocation = location[row] // 改变地点
}
if pickerView == timePickerView {
selectTime = row // 改变时间
}
}
}
心得:终於完赛了,这些天介绍了几个元件,也做了 1A2B 小游戏和这个天气 App,其实开赛前我本来预计还要做其它 App 出来的,但是那时候硬碟坏轨,导致许多写好的程序都不见,所以这 30 天来几乎是一天写一篇,写好程序再来写文章,即使是写过的还必须再写一次,实在是颇累人的,但是往好的方面想,这样可以让自己写过的东西记忆更深,即使忘掉了只要过来这里复制就好,也在这里看到了团队队友做过,而我却没做过的作品。
<<: [Day 28] Fortinet NSE Institute 免费网路安全培训课程
太太太感人了,中间几度想弃赛,这次中秋连假跟国庆连假估计让完赛人数下降不少,放假还要发文直比酷刑,而...
云端串流游戏加速推坑的开始~ (∩^o^)⊃━☆゚.*・。 线上游戏跟云端串流游戏的差异? 线上游戏...
在很多情况下,我们的任务前后之间没有必然的联系的,所以我们可以不需要等待前面命令结束,才开始后面的任...
本篇重点 Credit Enquires Short Stock Source Pandas Dat...
昨天简略的介绍了今天会布署的NATS,虽然NATS Streaming要被弃用了,不过我还是会介绍一...