[英]Swift 3 Compiler Errors with JSON and Dictionaries within URLSession.shared.dataTask
[英]Swift Methods Executing Out of Order as Program is Not Waiting for URLSession.shared.dataTask to Finish
我正在嘗試編寫一個應用程序,其中從API檢索數據並隨后顯示在應用程序視圖中。 問題是,當我運行代碼時,即使在getJson()函數之后調用它,在其中獲取視圖的setupViews()始終在檢索JSON數據之前運行。 getJson()函數先運行,但在“ URLSession.shared.dataTask(with:the_urlObj){(data,_,error)in”處停止,然后跳過該函數的其余部分,然后執行所有其余的在程序返回之前先運行。 在調用setupViews()函數之前,如何獲取完整的getJson()函數來執行?
我注意到,URLSession.shared.dataTask行是getJson()函數中的代碼停止的位置。 在setupViews()函數已經執行之后,它將返回到該代碼的其余部分。 我嘗試在URLSession.shared.dataTask行之后的getJson()塊中調用self.setupViews(),但是視圖仍然顯示而沒有數據。
// viewDidLoad函數
override func viewDidLoad() {
super.viewDidLoad()
getJson()
setupViews()
}
// getJson函數
func getJson(){
let jsonString = "https://api.openweathermap.org/data/2.5/weather?q=brooklyn,us&APPID=f942c97cab0e663a9a4882e6c3f0db1e"
guard let url = URL(string: jsonString) else { return }
URLSession.shared.dataTask(with: url) { (data,response,err) in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .secondsSince1970
let weatherData = try decoder.decode(WeatherData.self, from: data)
print("temperature: ", weatherData.main.temp)
// self.todays_weather.text = String("\(temperature)")
temperature = Int(weatherData.main.temp)
temperature = (temperature * 9/5)-459
}
catch {
print(err)
print(response)
}
}.resume()
}
//設置視圖功能
func setupViews(){
self.view.addSubview(todays_weather)
todays_weather.heightAnchor.constraint(equalToConstant: 140).isActive = true
todays_weather.widthAnchor.constraint(equalToConstant: 150).isActive = true
todays_weather.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
todays_weather.centerYAnchor.constraint(equalTo: self.view.topAnchor, constant: 120).isActive = true
self.view.addSubview(weather_button)
weather_button.heightAnchor.constraint(equalToConstant: 240).isActive = true
weather_button.widthAnchor.constraint(equalToConstant: 300).isActive = true
weather_button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
weather_button.centerYAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -90).isActive = true
}
let todays_weather : UITextField = {
let weather = UITextField()
weather.textColor = UIColor.black
weather.textAlignment = .center
weather.text = String("\(temperature)")
weather.font = UIFont.systemFont(ofSize:32)
weather.translatesAutoresizingMaskIntoConstraints = false
return weather
}()
代碼運行良好,但是視圖中的文本字段顯示為0而不是JSON檢索的溫度,因為由於getJson()函數在URLSession.shared處停止,因此setupViews()在JSON數據檢索完成之前就已執行。 dataTask。
我在控制台中收到此通知:2019-07-29 11:44:01.060026-0400 daily_tips [46459:8017625]從主線程訪問引擎后,此應用程序正在從后台線程修改AutoLayout引擎。 這會導致引擎損壞和奇怪的崩潰。
任何幫助,將不勝感激,謝謝!
歡迎來到StackOverflow! 對您來說,JSON提取是異步發生的,但是您在調用setupViews()
之后立即調用getJson()
。
一個好的解決方案是在getJson()
調用中添加一個完成處理程序。
func getJson(completionHandler: () -> ()){
let jsonString = "https://api.openweathermap.org/data/2.5/weather?q=brooklyn,us&APPID=f942c97cab0e663a9a4882e6c3f0db1e"
guard let url = URL(string: jsonString) else { return }
URLSession.shared.dataTask(with: url) { (data,response,err) in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .secondsSince1970
let weatherData = try decoder.decode(WeatherData.self, from: data)
print("temperature: ", weatherData.main.temp)
// self.todays_weather.text = String("\(temperature)")
temperature = Int(weatherData.main.temp)
temperature = (temperature * 9/5)-459
completionHandler()
}
catch {
print(err)
print(response)
}
}.resume()
}
然后在completionHandler中調用setupViews():
override func viewDidLoad() {
super.viewDidLoad()
getJson { [weak self] in
DispatchQueue.main.async {
self?.setupViews()
}
}
}
我建議搜索“ ios異步編程”和“ ios完成處理程序”以了解更多信息。 有很多很棒的信息,希望對您有所幫助。
沒有完成處理簡單的解決方案,把setupViews()
在完成處理dataTask
。
在openweathermap URL中使用參數units=imperial
,您將獲得所有華氏度。
override func viewDidLoad() {
super.viewDidLoad()
getJson()
}
func getJson(){
let jsonString = "https://api.openweathermap.org/data/2.5/weather?q=brooklyn,us&units=imperial&APPID=f942c97cab0e663a9a4882e6c3f0db1e"
guard let url = URL(string: jsonString) else { return }
URLSession.shared.dataTask(with: url) { [unowned self] data, response, error in
guard let data = data else { print(error!); return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .secondsSince1970
let weatherData = try decoder.decode(WeatherData.self, from: data)
print("temperature: ", weatherData.main.temp)
// self.todays_weather.text = String("\(temperature)")
temperature = Int(weatherData.main.temp)
DispatchQueue.main.async {
self.setupViews()
}
}
catch {
print(error)
print(response)
}
}.resume()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.