Search code examples
swiftclgeocoder

How to call CLGeocoder method synchronously


I have in ViewController code

var location = CLLocation()
    DispatchQueue.global().sync {
        let objLocationManager = clsLocationManager()
        location = objLocationManager.findLocationByAddress(address: self.txtTo.stringValue)
    }
    lblToLatitude.stringValue = String(location.coordinate.latitude)
    lblToLongitude.stringValue = String(location.coordinate.longitude)

calling findLocationByAddress method which is implemented in separate class clsLocationManager like this

func findLocationByAddress(address: String) -> CLLocation {
    let geoCoder = CLGeocoder()
    var location = CLLocation()
    geoCoder.geocodeAddressString(address, completionHandler: {(places, error) in
        guard error == nil else { return }
        location = places![0].location!
    })
    return location
}

I try to ensure via DispatchQueue.global().sync that geo-coding is executed before passing coordinates to lblToLatitude and lblToLongitude labels but it doesn't work. Of course I could do geo-coding in ViewController code but I'm wondering how to keep it in separate class.


Solution

  • You need a completion

    func findLocationByAddress(address: String,completion:@escaping((CLLocation?) -> ())) {
        let geoCoder = CLGeocoder() 
        geoCoder.geocodeAddressString(address, completionHandler: {(places, error) in
            guard error == nil else { completion(nil) ; return }
            completion(places![0].location!)
        }) 
    }
    

    to call

    findLocationByAddress { (location) in 
      if let location = location { 
          lblToLatitude.stringValue = String(location.coordinate.latitude)
          lblToLongitude.stringValue = String(location.coordinate.longitude)
      } 
    }
    

    Also no need for DispatchQueue.global().sync { as the geocoder runs asynchonously in a background thread