我试图从JSON格式的API获取给定时间段内的温度数组。我能够通过完成处理程序检索数组,但我无法将其保存到函数调用之外的另一个变量(使用完成处理程序的变量)。这是我的代码。请参阅评论区域。
class WeatherGetter {
func getWeather(_ zip: String, startdate: String, enddate: String, completion: @escaping (([[Double]]) -> Void)) {
// This is a pretty simple networking task, so the shared session will do.
let session = URLSession.shared
let string = "api address"
let url = URL(string: string)
var weatherRequestURL = URLRequest(url:url! as URL)
weatherRequestURL.httpMethod = "GET"
// The data task retrieves the data.
let dataTask = session.dataTask(with: weatherRequestURL) {
(data, response, error) -> Void in
if let error = error {
// Case 1: Error
// We got some kind of error while trying to get data from the server.
print("Error:\n\(error)")
}
else {
// Case 2: Success
// We got a response from the server!
do {
var temps = [Double]()
var winds = [Double]()
let weather = try JSON(data: data!)
let conditions1 = weather["data"]
let conditions2 = conditions1["weather"]
let count = conditions2.count
for i in 0...count-1 {
let conditions3 = conditions2[i]
let conditions4 = conditions3["hourly"]
let count2 = conditions4.count
for j in 0...count2-1 {
let conditions5 = conditions4[j]
let tempF = conditions5["tempF"].doubleValue
let windspeed = conditions5["windspeedKmph"].doubleValue
temps.append(tempF)
winds.append(windspeed)
}
}
completion([temps, winds])
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
// The data task is set up...launch it!
dataTask.resume()
}
}
I am calling this method from my view controller class. Here is the code.
override func viewDidLoad() {
super.viewDidLoad()
let weather = WeatherGetter()
weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30") { (weatherhandler: [[Double]]) in
//It prints out the correct array here
print(weatherhandler[0])
weatherData = weatherhandler[0]
}
//Here it prints out an empty array
print(weatherData)
}
答案 0 :(得分:0)
这不是一个错误,当你的controller
加载数组仍然是空的,因为你的getWeather
仍在做它的事情(意思是访问api,解码json)当它完成时callback
将data
返回您的控制器。
例如,如果您使用的是tableView,则在将数据分配给reloadData()
后,您将weatherData
刷新用户界面
或者您可以在声明property Observer
财产时放置weatherData
。
var weatherData:[Double]? = nil {
didSet {
guard let data = weatherData else { return }
// now you could do soemthing with the data, to populate your UI
}
}
现在,在将数据分配到wheaterData
后,将调用didSet
。
希望有所帮助,并将你的jsonParsing逻辑放入`struct :)
答案 1 :(得分:0)
问题是当数据返回"完成侦听器"时,API需要一些时间来返回数据。被调用,它进入" getWeather"方法实现,它打印数组的数据。但是当调用外部打印方法时,API还没有返回数据。所以它显示空数组。如果您将尝试打印数据表格" weatherData"对象在一段时间后会起作用。
我建议你的最好方法是使用" getWeather"中的数据更新你的用户界面。像这样的方法实现:
override func viewDidLoad() {
super.viewDidLoad()
let weather = WeatherGetter()
weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30") { (weatherhandler: [[Double]]) in
//It prints out the correct array here
print(weatherhandler[0])
weatherData = weatherhandler[0]
// Update your UI here.
}
//Here it prints out an empty array
print(weatherData)
}