Swift 从 api 可能的线程问题中获取价值
Swift get value from api possible threading issue
我有一个函数可以使用 google 的位置 api 执行 api 请求。从 api 响应数据中,我捕获了一个值并尝试将其设置为一个变量。该函数在另一个函数内部被调用。然后我尝试访问该变量,但不幸的是该变量还不包含该值。这似乎是一个线程问题,但我不知道如何解决。
更新:
我已经根据响应更新了代码。不幸的是,我仍然无法使用 api 请求中的值访问变量。我重写了执行 api 请求的函数以使用完成处理程序。 mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) 是 google 地图框架中的一个函数。我是否也需要重写它才能使用完成处理程序?
//变量
var website = ""
// 带有 api 请求的代码
func getWebsite2(id: String, completion: (result: String) -> Void) {
var url = NSURL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=\(id)&key=AIzaSyAWV1BUFv_vcedYroVrY7DWYuIxcHaqrv0")
self.dataTask = defaultSession.dataTaskWithURL(url!) {
data, respnse, error in
let json : AnyObject
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
var dictionArr = json["result"]
self.website = dictionArr!!["website"] as! String
print(self.website)
}
catch {
print(error)
}
}
self.dataTask?.resume()
}
// 第二个函数
func mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) {
let storeMarker = marker as! PlaceMarker
self.getWebsite2(storeMarker.id!) {
(result: String) in
print("inside did tap")
print(self.website)
// problem still here
// above two lines of code never run
}
self.performSegueWithIdentifier("toWebView", sender: nil)
}
// 我这样初始化defaultSession和dataTask。
let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var dataTask: NSURLSessionDataTask?
首先不要强制解包变量,并始终在需要的地方使用 do{} catch{}
。
这个小代码块展示了您应该如何处理 try
和 if let
条件:
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String:AnyObject]
if let dictionary = jsonObject["result"] as? [String: String] {
self.website = dictionary["website"]
} else {
print("Parse error")
}
} catch {
print("JSON error: \(error)")
}
其次defaultSession.dataTaskWithURL
是异步请求,只有在他完成时才会设置数据。
在另一个世界中,您尝试在请求未完成时打印值。
为了解决你的问题,你应该使用 Completion Handlers.
您没有调用传递给 getWebsite2
函数的完成处理程序。此(伪)代码显示了如何获取从服务器接收到的字符串并将其传递给在 didTapInfoWindowOfMarker
中调用的闭包。
func getWebsite2(id: String, completion: (result: String) -> Void) {
self.dataTask = defaultSession.dataTaskWithURL(url!) {
data, response, error in
// now on background thread
let someStringFromNetwork = data[0]
dispatch_async(dispatch_get_main_queue(),{
completion(someStringFromNetwork)
})
}
}
我有一个函数可以使用 google 的位置 api 执行 api 请求。从 api 响应数据中,我捕获了一个值并尝试将其设置为一个变量。该函数在另一个函数内部被调用。然后我尝试访问该变量,但不幸的是该变量还不包含该值。这似乎是一个线程问题,但我不知道如何解决。
更新: 我已经根据响应更新了代码。不幸的是,我仍然无法使用 api 请求中的值访问变量。我重写了执行 api 请求的函数以使用完成处理程序。 mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) 是 google 地图框架中的一个函数。我是否也需要重写它才能使用完成处理程序?
//变量
var website = ""
// 带有 api 请求的代码
func getWebsite2(id: String, completion: (result: String) -> Void) {
var url = NSURL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=\(id)&key=AIzaSyAWV1BUFv_vcedYroVrY7DWYuIxcHaqrv0")
self.dataTask = defaultSession.dataTaskWithURL(url!) {
data, respnse, error in
let json : AnyObject
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
var dictionArr = json["result"]
self.website = dictionArr!!["website"] as! String
print(self.website)
}
catch {
print(error)
}
}
self.dataTask?.resume()
}
// 第二个函数
func mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) {
let storeMarker = marker as! PlaceMarker
self.getWebsite2(storeMarker.id!) {
(result: String) in
print("inside did tap")
print(self.website)
// problem still here
// above two lines of code never run
}
self.performSegueWithIdentifier("toWebView", sender: nil)
}
// 我这样初始化defaultSession和dataTask。
let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var dataTask: NSURLSessionDataTask?
首先不要强制解包变量,并始终在需要的地方使用 do{} catch{}
。
这个小代码块展示了您应该如何处理 try
和 if let
条件:
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String:AnyObject]
if let dictionary = jsonObject["result"] as? [String: String] {
self.website = dictionary["website"]
} else {
print("Parse error")
}
} catch {
print("JSON error: \(error)")
}
其次defaultSession.dataTaskWithURL
是异步请求,只有在他完成时才会设置数据。
在另一个世界中,您尝试在请求未完成时打印值。 为了解决你的问题,你应该使用 Completion Handlers.
您没有调用传递给 getWebsite2
函数的完成处理程序。此(伪)代码显示了如何获取从服务器接收到的字符串并将其传递给在 didTapInfoWindowOfMarker
中调用的闭包。
func getWebsite2(id: String, completion: (result: String) -> Void) {
self.dataTask = defaultSession.dataTaskWithURL(url!) {
data, response, error in
// now on background thread
let someStringFromNetwork = data[0]
dispatch_async(dispatch_get_main_queue(),{
completion(someStringFromNetwork)
})
}
}