函数返回数组没有在 for 循环 Swift 中获得追加

Posted

技术标签:

【中文标题】函数返回数组没有在 for 循环 Swift 中获得追加【英文标题】:function returning array doesn't get the appends inside the for loop Swift 【发布时间】:2019-12-19 17:43:57 【问题描述】:

我是请求路线的新手,并关注 hackingwithswift (https://www.hackingwithswift.com/example-code/location/how-to-find-directions-using-mkmapview-and-mkdirectionsrequest) 的一篇文章,在跟踪新路线时,我能够获得刚刚跟踪的路线的替代路线。我的目标是输入[CLLocation]MKDirection 获取路线。问题是,在跟踪它时,我确实得到了一条替代路线,但是当从保存的路线(我刚刚跟踪的相同)请求它时,我得到一个 nil response 并显示错误消息:

方向错误:错误域=MKErrorDomain Code=1 "Indicazioni stradali non disponibili" UserInfo=NSLocalizedFailureReason=Le infoazioni sull'itinerario non sono attualmente disponibili., MKErrorGEOError=-12, MKErrorGEOErrorUserInfo= NSDebugDescription = "mapItem 不能为 nil"; , 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 在我打印时在forloop 内正确创建,但数组的大小不会增加,返回的数组只会有输入路由的第一个追加。

较新版本的函数是:

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】:

有几个问题:

首先,您正在尝试建立一条穿越整个美国的步行路线——这个问题无法通过常规方法解决。我建议将点的坐标设置在更近的距离。我已经在更近的地方测试了您的代码并出现了路线。

其次,你可以使用这个代码:

 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
        
    

【讨论】:

太好了,您回答时我正在更新问题。我确实认为这是一个异步问题。我不是把它打电话给整个美国,我不是一条 1.5 公里的路线.. @Vincenzo,好的。关于您的更新:您可以在单元格中使用回调来在单元格中显示您的结果。 For example 谢谢,我终于成功了,因为我在 while 循环中得到了响应,但我最终得到了一个仅包含第一个附加的 repositioned 数组在进入while 循环之前。我猜for 循环内部出了点问题。我在循环内打印point 并显示坐标,但由于某种原因它没有附加到repositionedarray。你明白为什么吗? @Vincenzo 能否提供代码,因为我不明白您在哪里、为什么以及如何使用 while 循环? 对不起,我在用代码更新问题之前回答了你。

以上是关于函数返回数组没有在 for 循环 Swift 中获得追加的主要内容,如果未能解决你的问题,请参考以下文章

在for循环中将PFFile数组转换为UIImage返回空数组Swift

Swift 3:如何使用 for 循环来循环数组

For循环用于搜索数组,Swift [重复]

如何在 Swift 3 中为我在 for 循环期间修改的数组编写 for 循环?

Js中数组的forEach()方法return无法退出循环

不能用swift在for循环中追加一个数组?