返回数组的函数无法在for循环Swift

时间:2019-12-19 17:43:57

标签: ios swift mkdirection

我不熟悉请求路线,并且跟随hackingwithswift(https://www.hackingwithswift.com/example-code/location/how-to-find-directions-using-mkmapview-and-mkdirectionsrequest)上的一篇文章,在跟踪新路线时,我可以获取到我刚刚跟踪的路线的替代路线。我的目标是输入一个[CLLocation]MKDirection的路线。问题是,在跟踪它时,我确实得到了一条替代路由,但是从保存的路由中请求它时(我刚刚跟踪过的路由),我得到了一条错误消息为nil response

  

方向错误:错误域= MKErrorDomain代码= 1“”指示   不可抗力” UserInfo = {NSLocalizedFailureReason = Le   不可抗力信息通报,,   MKErrorGEOError = -12,MKErrorGEOErrorUserInfo = {       NSDebugDescription =“ mapItem不能为零”; },MKDirectionsErrorCode = 3,NSLocalizedDescription = Indicazioni stradali   不可拒绝}

路线相同,因此起点和终点相同。你能看到我在做什么错吗? 一如既往的感谢。

 func repositionLocation(route: [CLLocation]) -> [CLLocation] {
    var repositioned: [CLLocation] = []
    let request = MKDirections.Request()
    request.requestsAlternateRoutes = false
    request.transportType = .walking
    let directions = MKDirections(request: request)
        let a = route.first?.coordinate
        let b = route.last?.coordinate
    print("a is: \(String(describing: a)), b is \(String(describing: b))") // prints correct CLLocationCoordinate2D
        request.source = MKMapItem(placemark: MKPlacemark(coordinate: a!))
        request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b!))

        directions.calculate { [unowned self] response, error in
            if let err = error {
                print("direction error : \(err)")
            }
            guard let unwrappedResponse = response else {print("no suggested routes available"); return } // here always returns
            guard let coord = unwrappedResponse.routes.first?.steps else {return}
            for location in coord {
                let point: CLLocation = CLLocation(latitude: location.polyline.coordinate.latitude, longitude: location.polyline.coordinate.longitude)
                repositioned.append(point)
            }
        }
    return repositioned
}

更新:

我正在缩小问题的范围,或者是我发出了太多请求(但我只发出了一个),而服务器停止了响应,或者由于响应是异步的,因此该函数在它可能实际获得有效响应之前退出,因为我从TableView调用它。 我将如何等待cellForRow中的响应?

更新2:

在提出了宝贵的建议之后,它现在正在请求路线并获得响应,从中我为每个步骤创建一个新的CLLocation并将其附加到repositioned数组中,并在完成后返回。 实际上,我在打印时发现在CLLocation循环中正确创建了新的for,但是数组的大小并没有增加,返回的数组仅包含输入的第一个追加路线。

该函数的较新版本为:

func repositionLocation(route: [CLLocation], completion: @escaping ([CLLocation]) -> Void) {
        var pos = 0
        var repositioned = [CLLocation]()
        repositioned.append(route.first!)
        guard route.count > 4 else {print("Reposision Location failed, not enough positions");return}
        let request = MKDirections.Request()
        request.requestsAlternateRoutes = false
        request.transportType = .walking
        while pos < route.count - 4 {

            let a = repositioned.last!.coordinate
            let b = route[pos + 4].coordinate
            request.source = MKMapItem(placemark: MKPlacemark(coordinate: a))
            request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b))
            let directions = MKDirections(request: request)
            directions.calculate { [unowned self] response, error in
                if let err = error {
                    print("direction error : \(err)")
                }
                guard let unwrappedResponse = response else {print("no suggested routes available"); return }
                print("Response is: \(unwrappedResponse.debugDescription)")
                guard let coord = unwrappedResponse.routes.first?.steps else {print("No coordinates");return}
                print("coord is: \(coord)")
                for location in coord {

                    let point: CLLocation = CLLocation(latitude: location.polyline.coordinate.latitude, longitude: location.polyline.coordinate.longitude)
                    print("point is: \(point)") // prints a correct CLLocation with coordinates
                    repositioned.append(point)
                    print("repositioned in for loop is : \(repositioned)") // prints just first appended location CLLocation with coordinates
                }
            }
            print("repositioned in while loop is : \(repositioned)")
            pos += 5
        }

        // last segment.
//        let a = repositioned.last?.coordinate
//        let b = route.last?.coordinate
//
//        request.source = MKMapItem(placemark: MKPlacemark(coordinate: a!))
//        request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b!))
//
//        let directions = MKDirections(request: request)
//
//        directions.calculate { [unowned self] response, error in
//            if let err = error {
//                print("direction error : \(err)")
//            }
//            guard let unwrappedResponse = response else {print("no suggested routes available"); return }
//            print("Response is: \(unwrappedResponse.debugDescription)")
//            guard let coord = unwrappedResponse.routes.first?.steps else {print("No coordinates");return}
//            for location in coord {
//                let point: CLLocation = CLLocation(latitude: location.polyline.coordinate.latitude, longitude: location.polyline.coordinate.longitude)
//                repositioned.append(point)
//            }

        print("repositioned at completion is : \(repositioned)")
            completion(repositioned)
//        }
    }

不要看注释掉的部分,它会处理输入路径的最后一部分,该部分超出了while循环内部处理的部分。

1 个答案:

答案 0 :(得分:0)

有几个问题:

首先,您正在尝试建立遍及美国的步行路线-这个问题无法通过传统方法解决。我建议将点的坐标设置得更近一些。我已经在更近的地方测试了您的代码,并且出现了该路线。

第二,您可以使用以下代码:

 func repositionLocation(route: [CLLocation], completion: @escaping ([CLLocation]) -> Void) {

        var repositioned = [CLLocation]()

        let request = MKDirections.Request()
        request.requestsAlternateRoutes = false
        request.transportType = .walking

        let a = route.first?.coordinate
        let b = route.last?.coordinate
        request.source = MKMapItem(placemark: MKPlacemark(coordinate: a!))
        request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b!))

        let directions = MKDirections(request: request)

        print("a is: \(String(describing: a)), b is \(String(describing: b))") // prints correct CLLocationCoordinate2D
        request.source = MKMapItem(placemark: MKPlacemark(coordinate: a!))
        request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b!))

        directions.calculate { response, error in
            if let err = error {
                print("direction error : \(err)")
            }
            guard let unwrappedResponse = response else {print("no suggested routes available"); return } // here always returns

            for route in unwrappedResponse.routes {
                self.mapView.addOverlay(route.polyline)
                self.mapView.setVisibleMapRect(route.polyline.boundingMapRect, animated: true)
            }

            guard let coord = unwrappedResponse.routes.first?.steps else {return}
            for location in coord {
                let point: CLLocation = CLLocation(latitude: location.polyline.coordinate.latitude, longitude: location.polyline.coordinate.longitude)
                repositioned.append(point)
            }
            completion(repositioned)
        }
}

您设置了let directions = MKDirections(request: request),但只有随后配置request.sourcerequest.destination。除此之外,您会异步获得结果,因此我为结果添加了completion

要进行测试,您可以这样称呼:

repositionLocation(route: [CLLocation(latitude: 40.7127, longitude: -74.0059), CLLocation(latitude: 40.79, longitude: -74.011)]) { result in
    print(result)
}

UPD2:

@Vincenzo,正如我所见,您错误地使用了完成处理程序进行关闭,我建议您完全阅读一下有关异步和关闭的信息。

我建议使用以下代码:

func repositionLocation(route: [CLLocation], completion: @escaping ([CLLocation]) -> Void) {
        var pos = 0
        var repositioned = [CLLocation]()
        repositioned.append(route.first!)

        guard route.count > 4 else {print("Reposision Location failed, not enough positions");return}
        let request = MKDirections.Request()
        request.requestsAlternateRoutes = false
        request.transportType = .walking

        while pos < route.count - 4 {

            let a = repositioned.last!.coordinate
            let b = route[pos + 4].coordinate
            request.source = MKMapItem(placemark: MKPlacemark(coordinate: a))
            request.destination = MKMapItem(placemark: MKPlacemark(coordinate: b))
            let directions = MKDirections(request: request)
            directions.calculate { [unowned self] response, error in
                if let err = error {
                    print("direction error : \(err)")
                }
                guard let unwrappedResponse = response else {print("no suggested routes available"); return }
                print("Response is: \(unwrappedResponse.debugDescription)")
                guard let coord = unwrappedResponse.routes.first?.steps else {print("No coordinates");return}
                print("coord is: \(coord)")
                for location in coord {

                    let point: CLLocation = CLLocation(latitude: location.polyline.coordinate.latitude, longitude: location.polyline.coordinate.longitude)
                    print("point is: \(point)") // prints a correct CLLocation with coordinates
                    repositioned.append(point)
                    print("repositioned in for loop is : \(repositioned)") // prints just first appended location CLLocation with coordinates
                }
                completion(repositioned)
            }
            print("repositioned in while loop is : \(repositioned)")
            pos += 5
        }
    }