[英]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.