0

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.

emsqre
  • 3
  • 7

3 Answers3

1

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 
      })
})
Caleb
  • 5,548
  • 3
  • 25
  • 32
  • Cool that worked! But it lags quite a bit for a few seconds and I am using parse PFGeoPoint to find objects that are near those coordinates but apparently something is not working right. – emsqre Aug 04 '15 at 03:19
  • Yeah it's a bit slow. The UI should not freeze anyways. Sorry, I'm not familiar with Parse so I don't know how much more assistance I can provide. – Caleb Aug 04 '15 at 03:22
  • Hey It was useful, I might use it at some point for other func which do not require immediate action. But thanks a lot! – emsqre Aug 04 '15 at 05:48
0

...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 --> ***
        }
    })
}
Igor F.
  • 2,649
  • 2
  • 31
  • 39
MirekE
  • 11,515
  • 5
  • 35
  • 28
  • Could you show me how to do it in a competition block? – emsqre Aug 04 '15 at 03:01
  • It is an IBAction, basically a search button. I am not sure I can do that? – emsqre Aug 04 '15 at 03:22
  • Whatever you need to do with the data must be initiated in the completion handler. If you provide more details about what exactly you want to do, the chances are that somebody will be able to give you more targeted answer... – MirekE Aug 04 '15 at 03:30
  • I just figured it out, I posted it as an answer as well. I basically had to pass the coordinates to query in the parse database to find the nearest cities after the user searched for them. But it seems to work. and Thanks again – emsqre Aug 04 '15 at 05:28
0

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()
 }
Edoardo
  • 657
  • 7
  • 24
emsqre
  • 3
  • 7