Json Swift:如何在异步urlsession函数中返回值?
如您所见,我正在接收一个JSON文件,使用SwiftyJSON对其进行解析,并尝试返回totalTime,但它不允许我这样做。我该怎么做Json Swift:如何在异步urlsession函数中返回值?,json,asynchronous,swift,nsurlsession,Json,Asynchronous,Swift,Nsurlsession,如您所见,我正在接收一个JSON文件,使用SwiftyJSON对其进行解析,并尝试返回totalTime,但它不允许我这样做。我该怎么做 func googleDuration(origin: String, destination: String) -> Int{ // do calculations origin and destiantion with google distance matrix api let originFix = origin.stringB
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();
}
您应该添加自己的
completionHandler
closure参数,并在任务完成时调用它:
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
}
如果调用者希望能够取消任务,我还需要返回NSURLSessionTask
不管怎样,你可以这样称呼它:
googleDuration(origin, destination: destination) { totalTime, error in
if let totalTime = totalTime {
// use totalTime here
} else {
// handle error
}
}
另一个例子:
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()
}
}
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
}
电话:
另一个例子:
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()
}
}
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
}
然后我在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)"
}
}
}
有没有办法让它非异步?我需要等待,直到有一个响应解析,但我不知道如何做。你的解决方案是对的,我想我的问题是错的,你可以,但这是严重不赞成的。这是一个可怕的用户体验,如果你在错误的时间做,看门狗程序可能会立即杀死你的应用程序。正确的解决方案是禁用UI,显示微调器(在iOS中,是一个
UIActivityIndicatorView
),并在请求完成时反转该过程。你真的应该接受异步模式,而不是反对它。顺便说一句,人们通常会将这些完成处理程序分派到主队列(因为调用方通常正在进行UI更新)。如果你想让我更新答案,告诉你怎么做,让我知道。如果你精通GCD,这可能是不言自明的,但如果你不精通,我很乐意向你展示。如果我这样做,它会将timeLabel设置为-999,而不是我想要的;googleDuration(startabel.text,destination:endLabel.text){totalTime,如果让totalTime=totalTime{//在这里使用totalTime tripTime=totalTime;println(tripTime);}}}println(“返回:”);println(tripTime);timeLabel.text=字符串(tripTime)代码>是的,所以它是self.timerLabel.text=…
。你把这个调度到主队列吗?BTW,而不是仅仅用“代码> +<代码>替换空间,你可以考虑做适当的百分比逃逸,如这里所概述的。