What I'm trying to do is pass a CLLocation
to the function getPlacemarkFromLocation
which then uses the passed CLLocation
through reverseGeocodeLocation
to set the CLPlacemark?
that will be returned.
I'm having issues creating the completionHandler
closure in reverseGeocodeLocation
, it's throwing a compiler error/crash:
In Swift, CLGeocodeCompletionHandler
is CLGeocodeCompletionHandler = (AnyObject[]!, NSError!) -> Void
according to the documentation AnyObject[]!
is supposed to contain CLPlacemark
objects just like the Objective-C version.
Here's my current code:
class func getPlacemarkFromLocation(location:CLLocation)->CLPlacemark?{
var g = CLGeocoder()
var p:CLPlacemark?
g.reverseGeocodeLocation(location, completionHandler: {
(placemarks, error) in
let pm = placemarks as? CLPlacemark[]
if (pm && pm?.count > 0){
p = placemarks[0] as? CLPlacemark
}
})
return p?
}
EDIT: It seems like the error had to do with placemarks.count
with placemarks
not being treated like an array. It compiles now, however I'm getting nothing but nil when trying to set p
inside the completionHandler
. I've checked the CLLocation
s being passed and they are valid.
EDIT 2: After printing placemarks
, I can confirm that it returns data. However p
is still returning nil.
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.