嗨,我想您刚刚遇到了异步编程的典型陷阱。您所做的是在任务从 URLSession 返回之前询问任务的返回值。你可以像这个例子一样自己制作一个完成处理程序来解决它,我从 Darksky 获得一些天气数据。请注意,您甚至不需要为此创建一个类,只需一个函数即可。
PS 注意我使用 Alamofire、SwiftyJSON 和 Gloss,这大大降低了使用 REST 接口的复杂性。这就是 Swift 3!
import Alamofire
import SwiftyJSON
import Gloss
typealias DarkSkyWeatherForecast = ( _ json : Gloss.JSON?, _ error : Error?) -> Void
func getWeatherForcast( latitude:Double, longitude:Double, completionHandler:@escaping DarkSkyWeatherForecast) -> Void {
let urlString = "https://api.darksky.net/forecast/"+darkSkyKey+"/"+String(latitude)+","+String(longitude)+"?units=si"
Alamofire.request(urlString).responseJSON { (response) in
if let resp = response.result.value {
let json = JSON(resp)
let glossJson = json.dictionaryObject
completionHandler( glossJson, nil)
}else{
completionHandler( nil, response.error)
}
}
}
并像这样调用函数:
getWeatherForcast(latitude: lat, longitude: lon) { (jsonArg, error) in
if error == nil{
guard let weather = DarkSkyWeather(json: jsonArg!) else {
self.effectView.removeFromSuperview()
return
}
if let ambTemp = weather.currently?.temperature, let windspd = weather.currently?.windSpeed, let windDir = weather.currently?.windBearing{
self.effectView.removeFromSuperview()
self.ambTemperature.text = String(ambTemp)
self.windSpeed.text = String( windspd )
self.windDirection.text = String( windDir )
self.getSpeed()
}
}else{
self.effectView.removeFromSuperview()
let alert = UIAlertController(title: "Error", message: "Could not get weather forecast", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
})
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
}
请注意,我仅在完成处理程序完成并实际返回一些数据或错误后才填充文本字段。忽略“效果视图”的东西,这是一个特殊的光标等待微调器:-)
并且了解这些映射到 json 数据的结构可能会有所帮助:
//common struct for weather data
public struct WeatherDataStruct : Decodable{
let time : Int?
let summary : String?
let icon : String?
let precipIntensity : Double?
let precipProbability : Double?
let precipType : String?
let temperature : Double?
let apparentTemperature : Double?
let dewPoint : Double?
let humidity: Double?
let windSpeed : Double?
let windBearing : Int?
let visibility : Double?
let cloudCover : Double?
let pressure : Double?
let ozone : Double?
public init?( json: JSON){
self.time = "time" <~~ json
self.summary = "summary" <~~ json
self.icon = "icon" <~~ json
self.precipIntensity = "precipIntensity" <~~ json
self.precipProbability = "precipProbability" <~~ json
self.precipType = "precipType" <~~ json
self.temperature = "temperature" <~~ json
self.apparentTemperature = "apparantTemperature" <~~ json
self.dewPoint = "dewPoint" <~~ json
self.humidity = "humidity" <~~ json
self.windSpeed = "windSpeed" <~~ json
self.windBearing = "windBearing" <~~ json
self.visibility = "visibility" <~~ json
self.cloudCover = "cloudCover" <~~ json
self.pressure = "pressure" <~~ json
self.ozone = "ozone" <~~ json
}
}
//hourly weather struct
public struct HourlyStruct : Decodable{
let summary : String?
let icon : String?
let data : [WeatherDataStruct]?
public init?(json: JSON) {
self.summary = "summary" <~~ json
self.icon = "icon" <~~ json
self.data = "data" <~~ json
}
}
//total struct for the whole json answer from darksky weather
public struct DarkSkyWeather : Decodable{
let latitude : Double?
let longitude : Double?
let timezone : String?
let offset : Int?
let currently : WeatherDataStruct?
let hourly : HourlyStruct?
public init?(json: JSON) {
self.latitude = "latitude" <~~ json
self.longitude = "longitude" <~~ json
self.timezone = "timezone" <~~ json
self.offset = "offset" <~~ json
self.currently = "currently" <~~ json
self.hourly = "hourly" <~~ json
}
}