Swift - CLGeocoder reverseGeocodeLocation completionHandler closure Swift - CLGeocoder reverseGeocodeLocation completionHandler closure ios ios

Swift - CLGeocoder reverseGeocodeLocation completionHandler closure


I found the answer I needed in this thread: Set address string with reverseGeocodeLocation: and return from method

The issue lies with the fact that reverseGeocodeLocation is asynchronous, the method is returning a value before the completionBlock sets p in my example.


As requested, here's my current code.

func showAddViewController(placemark:CLPlacemark){    self.performSegueWithIdentifier("add", sender: placemark) }func getPlacemarkFromLocation(location: CLLocation){    CLGeocoder().reverseGeocodeLocation(location, completionHandler:        {(placemarks, error) in            if error {println("reverse geodcode fail: \(error.localizedDescription)")}            let pm = placemarks as [CLPlacemark]            if pm.count > 0 { self.showAddPinViewController(placemarks[0] as CLPlacemark) }    })}

I didn't want to take the NSNotificationCenter route because that would add unnecessary overhead, rather inside the completionHandler closure I call upon another function and pass the CLPlacemark generated by getPlacemarkFromLocation as a parameter to keep things asynchronous since the function will be called after placemarks is set the function (should) receive the placemark needed and execute the code you want. Hope what I said makes sense.


With these lines of Swift, you can print out fully the location's address:

func getLocationAddress(location:CLLocation) {    var geocoder = CLGeocoder()    println("-> Finding user address...")    geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in        var placemark:CLPlacemark!        if error == nil && placemarks.count > 0 {            placemark = placemarks[0] as CLPlacemark            var addressString : String = ""            if placemark.ISOcountryCode == "TW" /*Address Format in Chinese*/ {                if placemark.country != nil {                    addressString = placemark.country                }                if placemark.subAdministrativeArea != nil {                    addressString = addressString + placemark.subAdministrativeArea + ", "                }                if placemark.postalCode != nil {                    addressString = addressString + placemark.postalCode + " "                }                if placemark.locality != nil {                    addressString = addressString + placemark.locality                }                if placemark.thoroughfare != nil {                    addressString = addressString + placemark.thoroughfare                }                if placemark.subThoroughfare != nil {                    addressString = addressString + placemark.subThoroughfare                }            } else {                if placemark.subThoroughfare != nil {                    addressString = placemark.subThoroughfare + " "                }                if placemark.thoroughfare != nil {                    addressString = addressString + placemark.thoroughfare + ", "                }                if placemark.postalCode != nil {                    addressString = addressString + placemark.postalCode + " "                }                if placemark.locality != nil {                    addressString = addressString + placemark.locality + ", "                }                if placemark.administrativeArea != nil {                    addressString = addressString + placemark.administrativeArea + " "                }                if placemark.country != nil {                    addressString = addressString + placemark.country                }            }            println(addressString)        }    })}

Cheers!


Here is closure that worked for me -- it took awhile to get it to work. I think your problem is related to not initializing p with the correct initializer. I tried a few variations until I got this to work: self.placemark = CLPlacemark(placemark: stuff[0] as CLPlacemark)

geocoder.reverseGeocodeLocation(newLocation, completionHandler: {(stuff, error)->Void in        if error {            println("reverse geodcode fail: \(error.localizedDescription)")            return        }        if stuff.count > 0 {            self.placemark = CLPlacemark(placemark: stuff[0] as CLPlacemark)            self.addressLabel.text = String(format:"%@ %@\n%@ %@ %@\n%@",                self.placemark.subThoroughfare ? self.placemark.subThoroughfare : "" ,                self.placemark.thoroughfare ? self.placemark.thoroughfare : "",                self.placemark.locality ? self.placemark.locality : "",                self.placemark.postalCode ? self.placemark.postalCode : "",                self.placemark.administrativeArea ? self.placemark.administrativeArea : "",                self.placemark.country ? self.placemark.country : "")        }        else {            println("No Placemarks!")            return        }        })

EDIT:

moved better answer to its own answer.