简体   繁体   English

函数返回数组不会在for循环Swift中获得追加

[英]function returning array doesn't get the appends inside the for loop Swift

I'm new to requesting routes and following an article from hackingwithswift ( https://www.hackingwithswift.com/example-code/location/how-to-find-directions-using-mkmapview-and-mkdirectionsrequest ) I am able to get an alternative route to the route I just tracked, when tracking a new one.我是新来请求路线并关注 hackingwithswift 的文章( https://www.hackingwithswift.com/example-code/location/how-to-find-directions-using-mkmapview-and-mkdirectionsrequest )我能够在跟踪新路线时,获取我刚刚跟踪的路线的替代路线。 My goal is to input a [CLLocation] get a route from MKDirection .我的目标是输入一个[CLLocation]MKDirection获取路线。 The problem is that when tracking it, I do get an alternative route, but when requesting it from a saved route ( the same I just tracked ) I get a nil response with the error message :问题是,在跟踪它时,我确实得到了一条替代路线,但是当从保存的路线(与我刚刚跟踪的路线相同)请求它时,我得到了一个带有错误消息的 nil response

direction error : Error Domain=MKErrorDomain Code=1 "Indicazioni stradali non disponibili" UserInfo={NSLocalizedFailureReason=Le informazioni sull'itinerario non sono attualmente disponibili., MKErrorGEOError=-12, MKErrorGEOErrorUserInfo={ NSDebugDescription = "mapItem cannot be nil";方向错误:Error Domain=MKErrorDomain Code=1 "Indicazioni stradali non disponibili" UserInfo={NSLocalizedFailureReason=Le informazioni sull'itinerario non sono attualmente disponibili., MKErrorGEOError=-12, MKErrorGEOErrorUserInfo={ NSDebugDescription be nilmap; }, MKDirectionsErrorCode=3, NSLocalizedDescription=Indicazioni stradali non disponibili} }, MKDirectionsErrorCode=3, NSLocalizedDescription=Indicazioni stradali non disponibili}

Route is the same, so identical starting and ending.路线是一样的,所以起点和终点都一样。 Can you see what I'm doing wrong here?你能看到我在这里做错了什么吗? As always many thanks.一如既往,非常感谢。

 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
}

Update :更新 :

I'm narrowing down the problem being either I make too many requests(but I'm making only one) and servers stop responding, or, being the response asynchronous, the function exits before it could actually get a valid response as I'm calling it from a TableView.我正在缩小问题的范围,要么我发出了太多请求(但我只发出一个请求)并且服务器停止响应,要么响应异步,该函数在实际获得有效响应之前退出从 TableView 调用它。 How would I wait for the response in cellForRow ?我将如何等待cellForRow的响应?

Update 2:更新 2:

After precious suggestions it's now requesting route and getting responses, from which I create a new CLLocation for every step, and append it to the repositioned array that gets returned on completion.经过宝贵的建议,它现在正在请求路由并获得响应,从中我为每一步创建一个新的CLLocation ,并将其附加到完成后返回的repositioned数组中。 I actually see that the new CLLocation gets created correctly inside the for loop as I print it, but the array doesn't increment in size, and the returned array will only have the first append from the input route.我实际上看到新的CLLocation在我打印时在for循环内正确创建,但数组的大小没有增加,并且返回的数组将只有输入路由中的第一个附加。

The newer version of the function is:该函数的较新版本是:

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

Don't look at the commented out portion, that will take care of the last bit of the input route that exceeds the part taken care of inside while loop .不要看注释掉的部分,它会处理超过while循环内部处理的部分的输入路由的最后一位。

There are several issues:有几个问题:

First of all, you are trying to build a walking route through the whole of USA - this problem cannot be solved by conventional methods.首先,您正在尝试建立一条穿越整个美国的步行路线 - 这个问题无法通过常规方法解决。 I recommend setting the coordinates of the points at a closer distance.我建议在更近的距离设置点的坐标。 I have tested your code at points closer and the route appears.我已经在更近的地方测试了您的代码,并且路线出现了。

Secondary, you can use this code:其次,您可以使用以下代码:

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

You set let directions = MKDirections(request: request) , but only then configure request.source and request.destination .您设置let directions = MKDirections(request: request) ,但只有这样才能配置request.sourcerequest.destination Other than that, you get the result asynchronously, so I added completion for result.除此之外,您会异步获得结果,因此我为结果添加了completion

For testing you can call this:对于测试,您可以调用它:

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

UPD2: UPD2:

@Vincenzo as I see, you incorrectly use completion handler for closure, I'd recommend to read about async and closure at all. @Vincenzo 如我所见,您错误地将完成处理程序用于关闭,我建议您阅读有关异步和关闭的全部内容。

I've recommend use this code:我建议使用此代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM