Swift: ¿Cómo devuelvo un valor dentro de una función de sesión de sesión asincrónica?

Como puede ver, recibo un archivo JSON, lo analizo usando SwiftyJSON y trato de devolver totalTime, pero no me lo permite. ¿Cómo hago esto?

func googleDuration(origin: String, destination: String) -> Int{ // do calculations origin and destiantion with google distance matrix api let originFix = origin.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil); let destinationFix = destination.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil); let urlAsString = "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+originFix+"&destinations="+destinationFix; println(urlAsString); let url = NSURL(string: urlAsString)! let urlSession = NSURLSession.sharedSession() let task = urlSession.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in if error != nil { // If there is an error in the web request, print it to the console println(error.localizedDescription) } println("parsing JSON"); let json = JSON(data: data); if (json["status"].stringValue == "OK") { if let totalTime = json["rows"][0]["elements"][0]["duration"]["value"].integerValue { println(totalTime); } } }) task.resume(); } 

Debe agregar su propio parámetro de cierre de fin de manipulador y llamarlo cuando la tarea finalice:

 func googleDuration(origin: String, destination: String, completionHandler: (Int?, NSError?) -> Void ) -> NSURLSessionTask { // do calculations origin and destiantion with google distance matrix api let originFix = origin.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil); let destinationFix = destination.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil); let urlAsString = "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+originFix+"&destinations="+destinationFix println(urlAsString) let url = NSURL(string: urlAsString)! let urlSession = NSURLSession.sharedSession() let task = urlSession.dataTaskWithURL(url) { data, response, error -> Void in if error != nil { // If there is an error in the web request, print it to the console // println(error.localizedDescription) completionHandler(nil, error) return } //println("parsing JSON"); let json = JSON(data: data) if (json["status"].stringValue == "OK") { if let totalTime = json["rows"][0]["elements"][0]["duration"]["value"].integerValue { // println(totalTime); completionHandler(totalTime, nil) return } let totalTimeError = NSError(domain: kAppDomain, code: kTotalTimeError, userInfo: nil) // populate this any way you prefer completionHandler(nil, totalTimeError) } let jsonError = NSError(domain: kAppDomain, code: kJsonError, userInfo: nil) // again, populate this as you prefer completionHandler(nil, jsonError) } task.resume() return task } 

También me gustaría devolver el NSURLSessionTask en caso de que la persona que llama desee poder cancelar la tarea.

De todos modos, llamarías esto así:

 googleDuration(origin, destination: destination) { totalTime, error in if let totalTime = totalTime { // use totalTime here } else { // handle error } } 

Otro ejemplo:

  class func getExchangeRate(#baseCurrency: String, foreignCurrency:String, completion: ((result:Double?) -> Void)!){ let baseURL = kAPIEndPoint let query = String(baseCurrency)+"_"+String(foreignCurrency) var finalExchangeRate = 0.0 if let url = NSURL(string: baseURL + query) { NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in if ((data) != nil) { let jsonDictionary:NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as NSDictionary if let results = jsonDictionary["results"] as? NSDictionary{ if let queryResults = results[query] as? NSDictionary{ if let exchangeRate = queryResults["val"] as? Double{ let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT dispatch_async(dispatch_get_global_queue(priority, 0)) { dispatch_async(dispatch_get_main_queue()) { completion(result: exchangeRate) } } } } } } else { completion(result: nil) } }.resume() } } 

Llamada:

  Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in if let exchangeValue = result { print(exchangeValue) } } 

Otro ejemplo:

 func getJason(url: NSURL, completionHandler: (String?, NSError?) -> Void ) -> NSURLSessionTask { var finalData: String! let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in if error != nil{ completionHandler(nil, error) return } else{ if let urlContent = data{ do{ let jsonData = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers) if let ip = jsonData["ip"]{ finalData = ip as? String completionHandler(finalData, nil) return } }catch{ print("EMPTY") } } } } task.resume() return task } 

Entonces lo llamé en el viewDidLoad

 getJason(url) { (ipAddress, error) -> Void in if error != nil{ print(error) } else{ if let ip = ipAddress{ //To get rid of optional self.ipLabelDisplay.text = "Your Ip Address is: \(ip)" } } }