Swift 无法等待MKDirections.calculate的结果,获取nil而不是它

Swift 无法等待MKDirections.calculate的结果,获取nil而不是它,swift,mapkit,xcode8,mkdirection,Swift,Mapkit,Xcode8,Mkdirection,我想使用MKDirections.calculate计算当前位置和CLLocations列表之间的实际步行距离。但是,由于某些原因,函数末尾的return命令并不等待结果,而是尝试返回空变量。我的代码如下所示: func getDistance (location1: CLLocation, location2: CLLocation) { let coordinates1 = location1.coordinate let placemark1 = MKPlacemark(c

我想使用
MKDirections.calculate
计算当前位置和
CLLocation
s列表之间的实际步行距离。但是,由于某些原因,函数末尾的return命令并不等待结果,而是尝试返回空变量。我的代码如下所示:

func getDistance (location1: CLLocation, location2: CLLocation) {
    let coordinates1 = location1.coordinate
    let placemark1 = MKPlacemark(coordinate: coordinates1)
    let sourceItem = MKMapItem(placemark: placemark1)
    let coordinates2 = location2.coordinate
    let placemark2 = MKPlacemark(coordinate: coordinates2)
    let destinationItem = MKMapItem(placemark: placemark2)

    let request = MKDirectionsRequest()
    request.source = sourceItem
    request.destination = destinationItem
    request.requestsAlternateRoutes = true
    request.transportType = .walking

    var distance: Double?

    let directions = MKDirections(request: request)
    directions.calculate { (response, error) in

        if var routeResponse = response?.routes {
            routeResponse.sort(by: {$0.expectedTravelTime < $1.expectedTravelTime})
            let quickestRoute: MKRoute = routeResponse[0]
            distance = Double(quickestRoute.distance)
        }
    }

    return distance //returns nil
}
let myLocation = CLLocation(latitude: 47.0, longitude: 17.0)
let destinationArray = [CLLocation(latitude: 47.1, longitude: 17.1), CLLocation(latitude: 47.2, longitude: 17.2), CLLocation(latitude: 47.3, longitude: 17.3)]
var distanceArray: [Double] = []
for destination in destinationArray {
    distanceArray.append(getDistance(location1: myLocation, location2: destination))
}
return distanceArray
我尝试过闭包,但它们不起作用,因为我找不到返回distanceArray的方法(同样的错误,它没有等待闭包运行并返回空数组)。我也尝试过DispatchGroup,但没有效果(可能是我以错误的方式实现了它们)

我非常感谢你的帮助


谢谢。

方向。calculate
是一个异步函数,因此在返回计算的距离之前,需要等待函数返回。您应该使用完成处理程序来完成此操作

func getDistance(location1: CLLocation, location2: CLLocation, completion: @escaping (Double) -> Void) {

    // etc 
    directions.calculate { (response, error) in

        if var routeResponse = response?.routes {
            routeResponse.sort(by: {$0.expectedTravelTime < $1.expectedTravelTime})
            let quickestRoute: MKRoute = routeResponse[0]

            completion(Double(quickestRoute.distance))
        }
    }
}
你可以称之为

getDistanceArray { distanceArray in
    print(distanceArray)
}

尝试以下关闭:

func getDistance (location1: CLLocation, location2: CLLocation,
    completion: @escaping(Double?) -> Void) {

    let coordinates1 = location1.coordinate
    let placemark1 = MKPlacemark(coordinate: coordinates1)
    let sourceItem = MKMapItem(placemark: placemark1)
    let coordinates2 = location2.coordinate
    let placemark2 = MKPlacemark(coordinate: coordinates2)
    let destinationItem = MKMapItem(placemark: placemark2)

    let request = MKDirectionsRequest()
    request.source = sourceItem
    request.destination = destinationItem
    request.requestsAlternateRoutes = true
    request.transportType = .walking

    var distance: Double?

    let directions = MKDirections(request: request)
    directions.calculate { (response, error) in

        if var routeResponse = response?.routes {
            routeResponse.sort(by: {$0.expectedTravelTime < $1.expectedTravelTime})
            let quickestRoute: MKRoute = routeResponse[0]
            distance = Double(quickestRoute.distance)
            completion(distance)
        }
    }
}
使用MapKit和Swift 5

计算两个位置之间的距离,它将帮助任何人

示例功能:我已经在谷歌地图和苹果地图上进行了测试

        let startLocation : CLLocation = CLLocation.init(latitude: 23.0952779, longitude: 72.5274129)
        let endLocation : CLLocation = CLLocation.init(latitude: 23.0981711, longitude: 72.5294229)
        let distance = startLocation.distance(from: endLocation)
        self.getDistance(departureDate: Date().adjust(hour: 8, minute: 0, second: 0, day: 0, month: 0), arrivalDate: Date().adjust(hour: 8, minute: 10, second: 0, day: 0, month: 0), startLocation: startLocation, endLocation: endLocation) { (distanceInMeters) in

            print("fake distance: \(distance)")
            let fakedistanceInMeter = Measurement(value: distance, unit: UnitLength.meters)
            let fakedistanceInKM = fakedistanceInMeter.converted(to: UnitLength.kilometers).value
            let fakedistanceInMiles = fakedistanceInMeter.converted(to: UnitLength.miles).value
            print("fakedistanceInKM :\(fakedistanceInKM)")
            print("fakedistanceInMiles :\(fakedistanceInMiles)")


            print("actualDistance : \(distanceInMeters)")

            let distanceInMeter = Measurement(value: distanceInMeters, unit: UnitLength.meters)
            let distanceInKM = distanceInMeter.converted(to: UnitLength.kilometers).value
            let distanceInMiles = distanceInMeter.converted(to: UnitLength.miles).value
            print("distanceInKM :\(distanceInKM)")
            print("distanceInMiles :\(distanceInMiles)")
        }

函数的使用

                    self.getDistance(departureDate: trip.departure.dateTime, arrivalDate: trip.arrival.dateTime, startLocation: startLocation, endLocation: endLocation) { (actualDistance) in
                        print("actualDistance : \(actualDistance)")
                    }

我对上述功能进行了改进,并在此处添加了代码,希望能对其他人有所帮助。

func calculateDistancefrom(departureDate: Date, arrivalDate: Date, sourceLocation: MKMapItem, destinationLocation: MKMapItem, doneSearching: @escaping (_ distance: CLLocationDistance) -> Void) {

        let request: MKDirections.Request = MKDirections.Request()

        request.departureDate = departureDate
        request.arrivalDate = arrivalDate

        request.source = sourceLocation
        request.destination = destinationLocation

        request.requestsAlternateRoutes = true
        request.transportType = .automobile

        let directions = MKDirections(request: request)
        directions.calculate { (directions, error) in
            if var routeResponse = directions?.routes {
                routeResponse.sort(by: {$0.expectedTravelTime <
                    $1.expectedTravelTime})
                let quickestRouteForSegment: MKRoute = routeResponse[0]

                doneSearching(quickestRouteForSegment.distance)
            }
        }
    }

    func getDistance(departureDate: Date, arrivalDate: Date, startLocation : CLLocation, endLocation : CLLocation, completionHandler: @escaping (_ distance: CLLocationDistance) -> Void) {

        let destinationItem =  MKMapItem(placemark: MKPlacemark(coordinate: startLocation.coordinate))
        let sourceItem      =  MKMapItem(placemark: MKPlacemark(coordinate: endLocation.coordinate))
        self.calculateDistancefrom(departureDate: departureDate, arrivalDate: arrivalDate, sourceLocation: sourceItem, destinationLocation: destinationItem, doneSearching: { distance in
            completionHandler(distance)
        })
    }
func calculatedInstanceFrom(出发日期:日期,到达日期:日期,源位置:mkmaItem,目的位置:mkmaItem,完成搜索:@escaping(u-distance:CLLocationDistance)->Void){
let请求:MKDirections.request=MKDirections.request()
request.departureDate=离开日期
request.arrivalDate=arrivalDate
request.source=sourceLocation
request.destination=destinationLocation
request.requestSalterRoutes=true
request.transportType=.automobile
let directions=MKDirections(请求:请求)
方向。计算{(方向,误差)
如果var RouterResponse=方向?.routes{
排序(按:{$0.expectedTravelTime<
$1.expectedTravelTime})
让QuicksRouteForSegment:MKRoute=routeResponse[0]
完成搜索(快速搜索路段距离)
}
}
}
func getDistance(出发日期:Date,到达日期:Date,startLocation:CLLocation,endLocation:CLLocation,completionHandler:@escaping(distance:CLLocationDistance)->Void){
设destinationItem=mkmaItem(placemark:MKPlacemark(坐标:startLocation.coordinate))
让sourceItem=MKMapItem(placemark:MKPlacemark(坐标:endLocation.coordinate))
self.calculatedInstanceFrom(出发日期:出发日期,到达日期:到达日期,源位置:sourceItem,destinationLocation:destinationItem,完成搜索:{distance in
completionHandler(距离)
})
}

对不起,我可以要求您帮助我在此之后如何返回最终距离数组吗?我在那里遇到了同样的问题,它只返回空数组。谢谢。更新了答案。不幸的是,出现了类似的问题:它只返回[]。你能帮帮我吗?非常感谢!我很快就会试试。请接受答案并投票表决@维克托尔西玛。祝你好运:-)
                    self.getDistance(departureDate: trip.departure.dateTime, arrivalDate: trip.arrival.dateTime, startLocation: startLocation, endLocation: endLocation) { (actualDistance) in
                        print("actualDistance : \(actualDistance)")
                    }

func calculateDistancefrom(departureDate: Date, arrivalDate: Date, sourceLocation: MKMapItem, destinationLocation: MKMapItem, doneSearching: @escaping (_ distance: CLLocationDistance) -> Void) {

        let request: MKDirections.Request = MKDirections.Request()

        request.departureDate = departureDate
        request.arrivalDate = arrivalDate

        request.source = sourceLocation
        request.destination = destinationLocation

        request.requestsAlternateRoutes = true
        request.transportType = .automobile

        let directions = MKDirections(request: request)
        directions.calculate { (directions, error) in
            if var routeResponse = directions?.routes {
                routeResponse.sort(by: {$0.expectedTravelTime <
                    $1.expectedTravelTime})
                let quickestRouteForSegment: MKRoute = routeResponse[0]

                doneSearching(quickestRouteForSegment.distance)
            }
        }
    }

    func getDistance(departureDate: Date, arrivalDate: Date, startLocation : CLLocation, endLocation : CLLocation, completionHandler: @escaping (_ distance: CLLocationDistance) -> Void) {

        let destinationItem =  MKMapItem(placemark: MKPlacemark(coordinate: startLocation.coordinate))
        let sourceItem      =  MKMapItem(placemark: MKPlacemark(coordinate: endLocation.coordinate))
        self.calculateDistancefrom(departureDate: departureDate, arrivalDate: arrivalDate, sourceLocation: sourceItem, destinationLocation: destinationItem, doneSearching: { distance in
            completionHandler(distance)
        })
    }