I am making a call to HERE Weather API from a mobile App and need to return the current weather as an object so that other methods can use that information for a given time period (eg. 30 min update intervals).
I have a rough understanding of asynchronous calls based on this site https://fluffy.es/return-value-from-a-closure/ but I am still running into my problem where I can't access the Weather object I create outside of the closure of the completionHandler.
I have provided the Get method from my Weather class. I have also provided a call to that Get method in the AppDelegates file.
public static func Get(lat:String, long:String, completionHandler: @escaping (Weather?) -> Void) {
//Keys go here
var request = URLRequest(
url: URL(string: "https://weather.cit.api.here.com/weather/1.0/report.json?app_code=-fJW5To2WdHdwQyYr_9ExQ&app_id=2m83HBDDcwAqTC2TqdLR&product=observation&latitude="+lat+"&longitude="+long+"&oneobservation=true")!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request, completionHandler: { dat, response, error in
do {
guard let json = try? JSONSerialization.jsonObject(with: dat as! Data, options: []) else {throw JSONParseError.missingJSON}
//parse json for dictionaries
guard let response = json as? [String: Any] else {throw JSONParseError.responseNotADictionary}
guard let observations = response["observations"] as? [String: Any] else {throw JSONParseError.observationsNotADictionary}
guard let locationJSON = observations["location"] as? [Any] else {throw JSONParseError.locationNotAnArray}
guard let location = locationJSON.first as? [String: Any] else {throw JSONParseError.locationNotADictionary}
guard let observationJSON = location["observation"] as? [Any] else {throw JSONParseError.observationNotAnArray}
guard let observation = observationJSON.first as? [String: Any] else {throw JSONParseError.observationNotADictionary}
//search dictionaries for values
guard let feedCreation = response["feedCreation"] as? String else {throw JSONParseError.missingFeedCreationObject}
guard let city = location["city"] as? String else {throw JSONParseError.missingCityObject}
guard let state = location["state"] as? String else {throw JSONParseError.missingStateObject}
guard let temperature = observation["temperature"] as? String else {throw JSONParseError.missingTemperatureObject}
guard let icon = observation["icon"] as? String else {throw JSONParseError.missingIconObject}
guard let iconName = observation["iconName"] as? String else {throw JSONParseError.missingIconNameObject}
//create weather object and return
guard let currentWeather = Weather(feedCreation: feedCreation,state: state,city: city,temperature: temperature,icon: icon,iconName: iconName) else {throw WeatherObjectCreationError.objectCreationFailed}
completionHandler(currentWeather)
} catch {
print("JSON Serialization error")
}
}).resume()
}
Weather.Get(lat:"32.9005", long:"-96.7869", completionHandler: {currentWeather in
if let testWeather = currentWeather{
//Works fine
print(testWeather.city)
print("completionHandler")
}
})
//Error says testWeather is not intialized
print(testWeather.city)
At the end of my Weather.Get call I should be able to access the testWeather object from other methods. Specifically, a method that modifies the speed limit based on the current weather in the area, which is returned by the Weather.Get call.