Reputation: 3
I have been banging my head in order to figure out how to fix this piece of code. Basically I have a piece of code that takes a string cityName and stores the latitude and longitude of it in a global variable and call it in another function right after. Apparently because of asynchronous call, I am not able to do that and the value of longitude and latitude are nil.
func findCityCoordinates(cityName: String) {
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(cityName, completionHandler: {(placemarks: [AnyObject]!, error: NSError!) -> Void in
if let placemark = placemarks?[0] as? CLPlacemark {
self.cityLatitude = placemark.location.coordinate.latitude //Returns nil
self.cityLongitude = placemark.location.coordinate.longitude //Returns nil
}
})
}
I have also been trying to work around completion handler but I have no idea on how to implement it and call it in a function. I would appreciate some help.
Upvotes: 0
Views: 1932
Reputation: 3
Well my brother helped me a little bit out on this, basically I wanted to run a completion block in the IBAction of the save button instead inside of the function findCityCoordinates:
func findCityCoordinate(city: String, completionHandler: (coordinate: CLLocationCoordinate2D) -> ()) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(city) { (placemarks: [AnyObject]!, error: NSError!) -> () in
if let placemark = placemarks[0] as? CLPlacemark {
let coordinate = placemark.location.coordinate
completionHandler(coordinate: coordinate)
}
}
}
And heres the function being called inside the saveButton action outlet:
findCityCoordinates(searchBar.text) { (cityCoordinate: CLLocationCoordinate2D) -> () in
self.queryForTable(cityCoordinate)
// Force reload of table data
self.myTableView.reloadData()
}
Upvotes: 0
Reputation: 11555
...stores the latitude and longitude of it in a global variable and call it in another function right after
I suspect that the other function is using it before the geocoder completion block sets the values. Put the call to the other function to the completion block, if possible.
func findCityCoordinates(cityName: String) {
var geocoder = CLGeocoder()
geocoder.geocodeAddressString(cityName, completionHandler: {(placemarks: [AnyObject]!, error: NSError!) -> Void in
if let placemark = placemarks?[0] as? CLPlacemark {
self.cityLatitude = placemark.location.coordinate.latitude //Returns nil
self.cityLongitude = placemark.location.coordinate.longitude //Returns nil
*** <-- call your function that uses location here --> ***
}
})
}
Upvotes: 0
Reputation: 5616
I was able to use the dispatch async for this. I declared two variables above the geocoder, assign them inside, and use them after it completes.
var lat:Float!
var long:Float!
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(cityName, completionHandler: {(placemarks: [AnyObject]!, error: NSError!) -> Void in
if let placemark = placemarks?[0] as? CLPlacemark {
lat = Float(placemark.location.coordinate.latitude)
long = Float(placemark.location.coordinate.longitude)
}
dispatch_async(
dispatch_get_main_queue(), {
self.cityLatitude = lat
self.cityLongitude = long
})
})
Upvotes: 1