Ios GCD信号不等待(Swift)
我对GCD还是个新手。我有这个函数用于前向地理编码,问题是它在完成关闭之前返回。所以每次它都返回零。我发现我可以使用信号量,因此返回将等待完成闭包,但是联机的示例很少,我没有发现任何返回的函数。我试图实现它,但函数仍然返回nil,即使稍后将位置打印到控制台。如果有人能告诉我哪里出了错,我将非常感激Ios GCD信号不等待(Swift),ios,swift,grand-central-dispatch,Ios,Swift,Grand Central Dispatch,我对GCD还是个新手。我有这个函数用于前向地理编码,问题是它在完成关闭之前返回。所以每次它都返回零。我发现我可以使用信号量,因此返回将等待完成闭包,但是联机的示例很少,我没有发现任何返回的函数。我试图实现它,但函数仍然返回nil,即使稍后将位置打印到控制台。如果有人能告诉我哪里出了错,我将非常感激 func forwardGeocoding(address: String) -> CLLocation? { var userLocation: CLLocation? var
func forwardGeocoding(address: String) -> CLLocation? {
var userLocation: CLLocation?
var returnvalue: CLLocation?
let semaphore = dispatch_semaphore_create(0)
CLGeocoder().geocodeAddressString(address, completionHandler: { (placemarks, error) in
if error != nil {
print("Geocoding error: \(error)")
return
}
if placemarks?.count > 0 {
let placemark = placemarks?.first
let location = placemark?.location
let coordinate = location?.coordinate
print("Settings location: \(coordinate!.latitude), \(coordinate!.longitude)")
if let unwrappedCoordinate = coordinate {
let CLReadyLocation: CLLocation = CLLocation(latitude: unwrappedCoordinate.latitude, longitude: unwrappedCoordinate.longitude)
userLocation = CLReadyLocation
dispatch_semaphore_signal(semaphore)
}
}
})
let wait = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
if wait != 0 {
returnvalue = userLocation
}
return returnvalue
}
调度信号量等待的结果在成功时为0,在超时时为非零。因此,您应该将代码更改为:
let wait=dispatch\u semaphore\u wait(semaphore,dispatch\u TIME\u ever)
另一点,您必须在块geocodeAddressString
结束执行之前调用dispatch\u semaphore\u signal
。否则,您的应用程序将永远等待,以防出现错误
CLGeocoder().geocodeAddressString(address, completionHandler: { (placemarks, error) in
if error != nil {
print("Geocoding error: \(error)")
dispatch_semaphore_signal(semaphore) //add to here
return
}
if placemarks?.count > 0 {
let placemark = placemarks?.first
let location = placemark?.location
let coordinate = location?.coordinate
print("Settings location: \(coordinate!.latitude), \(coordinate!.longitude)")
if let unwrappedCoordinate = coordinate {
let CLReadyLocation: CLLocation = CLLocation(latitude: unwrappedCoordinate.latitude, longitude: unwrappedCoordinate.longitude)
userLocation = CLReadyLocation
}
}
dispatch_semaphore_signal(semaphore) //and here
})
最后,当使用永远等待的信号量时,您必须确保信号量内的代码块将结束执行。正如Paulw11已经提到的,在这种情况下,信号量是非常糟糕的编程习惯。如果您是GCD新手,请学习理解在完成块中返回接收数据的异步模式。Swift比Objective-C更容易处理 这是一个使用完成块的示例:
func forwardGeocoding(address: String, completion: (CLLocation?, NSError?) -> Void) {
CLGeocoder().geocodeAddressString(address, completionHandler: { (placemarks, error) in
if error != nil {
completion(nil, error!)
} else {
if let placemarks = placemarks where !placemarks.isEmpty {
let placemark = placemarks.first!
if let unwrappedLocation = placemark.location {
let coordinate = unwrappedLocation.coordinate
print("Settings location: \(coordinate.latitude), \(coordinate.longitude)")
let CLReadyLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
completion(CLReadyLocation, nil)
}
}
}
})
}
并称之为
forwardGeocoding("foo") { (location, error) in
if error != nil {
print("Geocoding error: \(error!)")
} else {
// do something with the location
}
}
你走错了路。您应该将闭包传递给
forwardGeocoding
,并从完成处理程序调用它,而不是试图返回值。您当前的方法很可能会阻塞主队列,特别是在完成处理中,您并不是在所有情况下都像发信号一样发出信号!谢谢你的建议,我肯定需要进一步学习。再次非常感谢。如果您不介意的话,请您向我解释一下“If let placemarks=placemarks where!placemarks.isEmpty”行的具体功能是什么?这让我有点困惑,我很想知道:)没问题,如果让placemarks=placemarks
打开可选项,如果它不是nil
,那么where
子句检查数组是否为空。如果placemarks
不是nil
且不是空的,则if
条件为真isEmpty
是的同义词。count==0
forwardGeocoding("foo") { (location, error) in
if error != nil {
print("Geocoding error: \(error!)")
} else {
// do something with the location
}
}