Reputation: 408
I am building a function that takes a CLLocation
parameter and returns a Weather Forecast of type DarkSkyResponse
which I have defined myself.
public func getForecast(at location: CLLocation) -> DarkSkyResponse {
let request = DarkSkyRequest(key: "KEYGOESHERE")
let point = DarkSkyRequest.Point(location.coordinate.latitude, location.coordinate.longitude)
guard let url = request.buildURL(point: point) else {
preconditionFailure("Failed to construct URL")
}
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
DispatchQueue.main.async {
guard let data = data else {
fatalError("No Data Recieved")
}
guard let forecast = DarkSkyResponse(data: data) else {
fatalError("Decoding Failed")
}
return forecast
}
}
task.resume()
}
Everything works perfectly and I just want to return the forecast
variable found inside the DispatchQueue. When I tried to do this I was met with the following error:
Unexpected non-void return value in void function
I believe that this is because I am returning inside of the DispatchQueue.
To try and fix this I moved the data task and decoding process into it's own function that has a completion handler. When I call the function I just have the closure set to return the output as so:
public func getForecast(at location: CLLocation) -> DarkSkyResponse {
let request = DarkSkyRequest(key: "KEYGOESHERE")
let point = DarkSkyRequest.Point(location.coordinate.latitude, location.coordinate.longitude)
guard let url = request.buildURL(point: point) else {
preconditionFailure("Failed to construct URL")
}
func getDataAndDecode(from url: URL, completionBlock: @escaping (DarkSkyResponse) -> Void) -> Void {
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
DispatchQueue.main.async {
guard let data = data else {
fatalError("No Data Recieved")
}
guard let forecast = DarkSkyResponse(data: data) else {
fatalError("Decoding Failed")
}
completionBlock(forecast)
}
}
task.resume()
}
getDataAndDecode(from: url) { (output) in
return output
}
}
Now I get a warning saying: Expression of type 'DarkSkyResponse' is unused
. I am doing this the correct way or is there a more elegant way of returning the value I want?
Upvotes: 1
Views: 1831
Reputation: 66
As for now, swift doesn’t support yet for async await style (similar to javascript), that means you can’t return directly from async operation. You better put the callback(completionBlock) argument at getForecast method. And it would be nicely if the callback also handle the error case(e. g. onSuccess and onError). And don’t forget to set getForecast method as void method.
So it would be like these :
func getForecast(at location: CLLocation, onSuccess: (DarkSkyResponse) -> (), onError: (Error) -> ()) {
...
}
Upvotes: 2