Не могу дождаться результата MKDirections.calculate, получая ноль вместо него - PullRequest
0 голосов
/ 28 августа 2018

Я хотел бы рассчитать реальное расстояние пешком между моим текущим местоположением и списком CLLocation с использованием MKDirections.calculate. Однако по какой-то причине команда возврата в конце функции не ожидает результата и пытается вернуть пустую переменную. Мой код выглядит так:

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 (та же ошибка, он не дождался выполнения замыкания и возвратил пустой массив). Я также пробовал DispatchGroups, но они не имели никакого эффекта (возможно, я реализовал их неправильно).

Буду очень признателен за вашу помощь.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Попробуйте следующее закрытие:

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)
        }
    }
}

Использование:

    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 {
        getDistance(location1: myLocation, location2: destination) { distance in
            print("distance", distance)
            if let distance = distance {
                distanceArray.append(distance)
            }
        }
    }
    return distanceArray
0 голосов
/ 28 августа 2018

directions.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))
        }
    }
}

и затем вы должны сделать что-то похожее с вашим массивом расстояний. Вам нужно будет подождать, пока все getDistance звонки не вернутся, поэтому вы можете использовать DispatchGroup для этого…

func getDistanceArray(completion: @escaping ([Double]) -> Void) {

    let group = DispatchGroup()
    var distanceArray: [Double] = []

    for destination in destinationArray {
        group.enter()
        getDistance(location1: myLocation, location2: destination) { distance in
            distanceArray.append(distance)
            group.leave()
        }
    }
    group.wait()
    completion(distanceArray)
}

который вы можете назвать ...

getDistanceArray { distanceArray in
    print(distanceArray)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...