使用MKDirections实例的计算方法

时间:2019-02-22 14:39:58

标签: ios swift xcode

在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

任何人都可以解决此问题吗?谢谢。

2 个答案:

答案 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()。一旦enterleave调用计数具有相同的值,将执行dispatchGroup.notify的闭包。 请注意,我用半开范围 0...countySites.count - 1替换了您的近距离范围 0 ..< countySites.count

亲切问候

答案 1 :(得分:0)

已实施建议,现在可以使用。