[英]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
}
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
的响应?
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.source
和request.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.