Salut, je pense que vous venez de rencontrer l'écueil typique de la programmation asynchrone. Ce que vous faites, c'est demander la valeur de retour de la tâche, avant qu'elle ne revienne de l'URLSession. Vous pouvez le résoudre en créant vous-même un gestionnaire de complétion comme dans cet exemple, où je reçois des données météo de Darksky. Notez que vous n'avez même pas besoin de faire une classe pour cela, juste une fonction. PS: j'utilise Alamofire, SwiftyJSON et Gloss, ce qui réduit considérablement la complexité en utilisant les interfaces REST. Et voici 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)
}
}
}
Et l'appel de la fonction comme ceci:
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)
}
}
Remarque, je ne remplir que les champs de texte une fois que le gestionnaire d'achèvement est terminé et retourne en fait soit des données ou une erreur. Ne tenez pas compte de la substance « effectView », qui est une curser spéciale attente spinner :-)
Et aussi de connaître ces struct qui est mis en correspondance avec les données JSON pourrait être helpfull:
//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
}
}
Vous pouvez utiliser processus de délégation pour récupérer le rappel avec votre tableau 'details' en tant que paramètre dans votre viewcontroller.Maintenant, regardez comment implémenter le délégué avec le protocole dans swift. – Tann