ray ray - 2 months ago 11
Swift Question

Swift get value from api possible threading issue

I have a function that does an api request using google's places api. From the api response data I capture a value and try to set it to a variable. This function is called inside another function. I then try to access that variable but unfortunately the variable doesn't contain the value yet. This appears to be a threading issue but I don't know how to fix it.

update:
I have updated the code based on the responses. Unfortunately I am still not able to access the variable with the value from the api request. I have rewrote the function that does the api request to use a completion handler. The mapView(mapView: GMSMapView!, didTapInfoWindowOfMarker marker: GMSMarker!) is a function from the google maps framework. Would I need to rewrite this as well to use take a completion handler ?

// variable

var website = ""


// code with api request

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()
}


// second function

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)
}


// I initialize defaultSession and dataTask like this.

let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var dataTask: NSURLSessionDataTask?

Answer

You are not invoking the completion handler passed into the getWebsite2 function. This (pseudo)code shows how to take the string received from the server and pass it to the closure invoked in 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)
        })
    }
}
Comments