我刚接触到swift中的闭包,并想知道如何从闭包中取回我的注释。我知道,因为它是异步的,外部数组不会在正确的时间填满。
我应该使用类似完成处理程序的东西吗?我怎么做?这是什么最好的做法?具有回调的函数从didupdateLocation
调用。
fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int) -> Array<GMAnnotation>
{
var annotations: [GMAnnotation] = []
placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in
if let error = error {
print("Current Place error: \(error.localizedDescription)")
return
}
if let likelihoodList = placeLikelihoods {
for likelihood in likelihoodList.likelihoods {
let annotation = GMAnnotation()
let place = likelihood.place
annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
annotations.append(annotation)
}
}
})
return annotations; ====> EMPTY
答案 0 :(得分:3)
是的,您需要在函数中添加@escaping
闭包。请记住,异步函数会改变应用程序的工作方式 - 例如,如果要在表视图中显示此数据,则需要调用tableView.reloadData()
(或其中一种兄弟方法)来实际更新数据可用后的表格。这是带闭包的函数:
fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int, closure: @escaping (Array<GMAnnotation>) -> Void) {
var annotations: [GMAnnotation] = []
placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in
if let likelihoodList = placeLikelihoods {
for likelihood in likelihoodList.likelihoods {
let annotation = GMAnnotation()
let place = likelihood.place
annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
annotations.append(annotation)
}
closure(annotations)
}
})
}
调用它时,更新表视图的数据源,然后重新加载表视图:
getGooglePoisForCurrentLocationclosure(closure: { (annotations) -> Void in
tableViewDataSourceArray = annotations
tableView.reloadData()
})
作为旁注,这个例子不是特别安全 - 没有错误检查,返回类型不是可选的 - 如果API调用失败,它可能会崩溃。这是相同函数的更强大版本,它处理错误和正确的返回类型:
enum PlacesResult {
case success(Array<GMAnnotation>)
case error(Error)
}
fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int, closure: @escaping (PlacesResult) -> Void) {
var annotations: [GMAnnotation] = []
placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in
if let error = error {
print("Current Place error: \(error.localizedDescription)")
closure(PlacesResult.error(error))
}
if let likelihoodList = placeLikelihoods {
for likelihood in likelihoodList.likelihoods {
let annotation = GMAnnotation()
let place = likelihood.place
annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
annotations.append(annotation)
}
closure(PlacesResult.success(annotations))
} else {
closure(PlacesResult.error(Error()))
// something else went wrong but we still want this to call the closure.
}
})
}
答案 1 :(得分:1)
嗯,currentPlace
来电是异步的,因此您无法立即在getGooglePoisForCurrentLocation
函数中返回任何内容。
你可以做这样的事情,具体取决于你的需求:
tableView.reloadData
或ViewController中的其他内容)来更新UI。请注意,必须在主线程中执行此类调用(您可以使用DispatchQueue.main.async
来执行此操作)