I'm trying to delay a segue until I get a response from a reverseGeocodeLocation
call. However, when using breakpoints to check when the value actually changes, it's still happening after the UI transition occurs. I've tried having the function be a void and with the current String
return.
EDITED CODE:
func getReversedGeocodeLocation(completionHandler: (String, NSError?) ->()) {
let semaphore = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in
CLGeocoder().reverseGeocodeLocation(self.newMeetupLocation, completionHandler: {(placemarks, error) -> Void in
if error != nil {
print("Reverse geocoder failed with error" + error!.localizedDescription)
return
}
else if placemarks?.count > 0 {
}
else {
print("Problem with the data received from geocoder")
}
completionHandler(placemarks!.first!.name! ?? "", error)
})
dispatch_semaphore_signal(semaphore)
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
OLD CODE:
let semaphore = dispatch_semaphore_create(1) //even with 0, it's not working
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in
self.newAddress = self.getReversedGeocodeLocation()
dispatch_semaphore_signal(semaphore)
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
//dispatch_semaphore_signal(semaphore)
print(self.newAddress + ".")
self.performSegueWithIdentifier("mainToNewAddress", sender: self)
func getReversedGeocodeLocation() -> String{
var address = ""
CLGeocoder().reverseGeocodeLocation(self.newAddressLocation, completionHandler: {(placemarks, error) -> Void in
if error != nil {
print("Reverse geocoder failed with error" + error!.localizedDescription)
return
}
else if placemarks?.count > 0 {
let pm = placemarks?.first!
address = pm!.name!
}
else {
print("Problem with the data received from geocoder")
}
})
return address
}
Using a semaphore and dispatching the call to getReversedGeocodeLocation
is unnecessarily complicated. CLGeocoder().reverseGeocodeLocation
is already asynchronous. If you simply pass a completion handler closure to getReversedGeocodeLocation
then you can use that to invoke the segue;
self.getReversedGeocodeLocation(self.newAddressLocation, completionHandler: { (address,error) in
guard error == nil else {
print("Reverse geocoder failed with error" + error!.localizedDescription)
return
}
guard let address = address else {
print("No address returned")
return
}
self.newAddress = address
dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier("mainToNewAddress", sender: self)
})
})
func getReversedGeocodeLocation(addressLocation: String, completionHandler:((address: String?, error: NSError?) -> Void))) {
CLGeocoder().reverseGeocodeLocation(self.newAddressLocation, completionHandler: {(placemarks, error) -> Void in
var address = nil
if placeMarks.count > 0 {
if let pm = placeMarks!.first {
address = pm.name
}
} else {
print("Problem with the data received from geocoder")
}
completionHandler(address,error)
})
}
I dont think its a problem with the semaphore, its with your getReversedGeocodeLocation
function. the CLGeocoder().reverseGeocodeLocation
is an async function, therefore the return statement is going to execute before the completion block of CLGeocoder().reverseGeocodeLocation
is executed, which is why self.newAddress
is being assigned an empty string.
To fix this you could use another semaphore inside the getReversedGeocodeLocation
to block until the completion handler is finished, or use a delegate to notify something that the completion handler is finished (which is usually the right way to do it).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.