在for循环中使用MKDirections对象的计算方法时,我遇到了一个非常奇怪的问题。我的代码计算了从用户当前位置到3个不同营地的位置之间的距离,但并不是所有距离都在代码中的同一点计算出来。这是下面的代码;
for siteIndex in 0...countySites.count - 1 {
var selectedSite = countySites[siteIndex]
let destinationPlacemark = MKPlacemark(coordinate: selectedSite.locationCoordinate)
request.destination = MKMapItem(placemark: destinationPlacemark)
let distanceAndDirections = MKDirections(request: request)
if currentCoordinate != nil {
distanceAndDirections.calculate { (response, error) in
if error == nil {
let distanceInMetres = response?.routes.first?.distance
let distanceInMiles = distanceInMetres! / 1610
let roundedDistanceInMiles = Int(distanceInMiles.rounded())
distanceToSite = roundedDistanceInMiles
selectedSite.distance = distanceToSite
self.countySites[siteIndex] = selectedSite
print("distanceToSite = \(distanceToSite)")
if self.countySites.count > 1 {
if siteIndex == self.countySites.count - 1 {
print("BEFORE: countySites[0].distance = \(self.countySites[0].distance)")
print("BEFORE: countySites[1].distance = \(self.countySites[1].distance)")
print("BEFORE: countySites[2].distance = \(self.countySites[2].distance)")
self.countySites = self.sortByDistance(sites: self.countySites)
print("AFTER: countySites[0].distance = \(self.countySites[0].distance)")
print("AFTER: countySites[1].distance = \(self.countySites[1].distance)")
print("AFTER: countySites[2].distance = \(self.countySites[2].distance)")
self.tableView.reloadData()
}
}
} else {
print("Distance error: \(error.debugDescription)")
}
}
} else {
print("currentCoordinate is nil")
}
}
在设备上运行代码时,我得到以下输出;
Got here!
distanceToSite = 224
distanceToSite = 235
BEFORE: countySites[0].distance = 224
BEFORE: countySites[1].distance = -1
BEFORE: countySites[2].distance = 235
AFTER: countySites[0].distance = -1
AFTER: countySites[1].distance = 224
AFTER: countySites[2].distance = 235
distanceToSite = 235
任何人都可以解决此问题吗?谢谢。
答案 0 :(得分:0)
由于calculate(completionHandler:)
以异步方式返回值,因此不能保证一旦到达列表中的最后一个元素,就计算出所有距离。
要实现您所需要的,您必须执行以下操作:
let dispatchGroup = DispatchGroup()
for siteIndex in 0 ..< countySites.count {
var selectedSite = countySites[siteIndex]
if let currentCoordinate = currentCoordinate {
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: currentCoordinate))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: selectedSite.locationCoordinate))
let distanceAndDirections = MKDirections(request: request)
dispatchGroup.enter()
distanceAndDirections.calculate { (response, error) in
if error == nil {
let distanceInMetres = response?.routes.first?.distance
let distanceInMiles = distanceInMetres! / 1610
let roundedDistanceInMiles = Int(distanceInMiles.rounded())
let distanceToSite = roundedDistanceInMiles
selectedSite.distance = distanceToSite
countySites[siteIndex] = selectedSite
print("distanceToSite = \(distanceToSite)")
} else {
print("Distance error: \(error.debugDescription)")
}
dispatchGroup.leave()
}
} else {
print("currentCoordinate is nil")
}
}
dispatchGroup.notify(queue: .main) {
print("BEFORE: countySites[0].distance = \(self.countySites[0].distance)")
print("BEFORE: countySites[1].distance = \(self.countySites[1].distance)")
print("BEFORE: countySites[2].distance = \(self.countySites[2].distance)")
self.countySites = self.sortByDistance(sites: self.countySites)
print("AFTER: countySites[0].distance = \(self.countySites[0].distance)")
print("AFTER: countySites[1].distance = \(self.countySites[1].distance)")
print("AFTER: countySites[2].distance = \(self.countySites[2].distance)")
self.tableView.reloadData()
}
您必须先创建DispatchGroup
并调用dispatchGroup.enter()
,然后再调用calculate(completionHandler:)
。在相同方法的completionHandler中,必须调用dispatchGroup.leave()
。一旦enter
和leave
调用计数具有相同的值,将执行dispatchGroup.notify
的闭包。
请注意,我用半开范围 0...countySites.count - 1
替换了您的近距离范围 0 ..< countySites.count
。
亲切问候
答案 1 :(得分:0)
已实施建议,现在可以使用。