问题
As you can see, I'm receiving a JSON file, parsing it using SwiftyJSON, and trying to return totalTime, but it won't let me. How do I do this?
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();
}
回答1:
You should add your own completionHandler
closure parameter and call it when the task completes:
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
}
I'd also have this return the NSURLSessionTask
in case the caller wants to be able to cancel the task.
Anyway, you'd call this like so:
googleDuration(origin, destination: destination) { totalTime, error in
if let totalTime = totalTime {
// use totalTime here
} else {
// handle error
}
}
回答2:
Another example:
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()
}
}
Call:
Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in
if let exchangeValue = result {
print(exchangeValue)
}
}
回答3:
Another example:
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
}
Then i called it in the 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)"
}
}
}
来源:https://stackoverflow.com/questions/27081062/swift-how-do-i-return-a-value-within-an-asynchronous-urlsession-function