Swift 信号量在调用 UI 之前不等待函数完成
Swift semaphore not waiting for function to finish before calling UI
我正在尝试延迟 segue,直到收到 reverseGeocodeLocation
呼叫的响应。但是,当使用断点检查值何时实际更改时,它仍然在 UI 转换发生后发生。我试过让函数为空,并使用当前的 String
return.
编辑代码:
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)
}
旧代码:
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
}
我认为这不是信号量的问题,而是您的 getReversedGeocodeLocation
函数的问题。 CLGeocoder().reverseGeocodeLocation
是一个异步函数,因此 return 语句将在 CLGeocoder().reverseGeocodeLocation
的完成块执行之前执行,这就是为什么 self.newAddress
被分配一个空字符串.
要解决此问题,您可以在 getReversedGeocodeLocation
中使用另一个信号量来阻塞,直到完成处理程序完成,或者使用委托来通知完成处理程序已完成(这通常是正确的方法去做)。
使用信号量并将调用分派给 getReversedGeocodeLocation
不必要地复杂。 CLGeocoder().reverseGeocodeLocation
已经是异步的。如果您只是将完成处理程序闭包传递给 getReversedGeocodeLocation
,那么您可以使用它来调用 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)
})
}
我正在尝试延迟 segue,直到收到 reverseGeocodeLocation
呼叫的响应。但是,当使用断点检查值何时实际更改时,它仍然在 UI 转换发生后发生。我试过让函数为空,并使用当前的 String
return.
编辑代码:
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)
}
旧代码:
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
}
我认为这不是信号量的问题,而是您的 getReversedGeocodeLocation
函数的问题。 CLGeocoder().reverseGeocodeLocation
是一个异步函数,因此 return 语句将在 CLGeocoder().reverseGeocodeLocation
的完成块执行之前执行,这就是为什么 self.newAddress
被分配一个空字符串.
要解决此问题,您可以在 getReversedGeocodeLocation
中使用另一个信号量来阻塞,直到完成处理程序完成,或者使用委托来通知完成处理程序已完成(这通常是正确的方法去做)。
使用信号量并将调用分派给 getReversedGeocodeLocation
不必要地复杂。 CLGeocoder().reverseGeocodeLocation
已经是异步的。如果您只是将完成处理程序闭包传递给 getReversedGeocodeLocation
,那么您可以使用它来调用 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)
})
}