DEV Community

Khoa Pham
Khoa Pham

Posted on

How to request direction for GMSMapView using MapKit

Due to policy, we can't use Google Directions API on MKMapView, but we can use MKDirections on GMSMapView. Code is in Swift 5

MKDirections

A utility object that computes directions and travel-time information based on the route information you provide.

let source = MKMapItem(placemark: MKPlacemark(coordinate: userLocation.coordinate))
let destination = MKMapItem(placemark: MKPlacemark(coordinate: store.toCoordinate())
let request = MKDirections.Request()
request.source = source
request.destination = destination
request.requestsAlternateRoutes = fals
let directions = MKDirections(request: request
directions.calculate(completionHandler: { (response, error) in

})

MKRoute to CLLocationCoordinate2D

MKPolyline inherits from MKMultiPoint

let route = response.routes[0]

var coordinates = [CLLocationCoordinate2D](
    repeating: kCLLocationCoordinate2DInvalid,
    count: route.polyline.pointCount
)

route.polyline.getCoordinates(
    &coordinates,
    range: NSRange(location: 0, length: route.polyline.pointCount)
)

Google encoded polyline algorithm

Polyline encoding is a lossy compression algorithm that allows you to store a series of coordinates as a single string. Point coordinates are encoded using signed values.

Google's direction API provides points along route segments as an encoded string. For example the encoded string:

_p~iF~ps|U_ulLnnqC_mqNvxq`@

decodes to the coordinate points:

(38.5, -120.2), (40.7, -120.95), (43.252, -126.453)

Encode a CLLocationCoordinate2D array to a polyline

`swift
import Polyline

private func googlePolylines(from response: MKDirections.Response) -> [GMSPolyline] {
let polylines: [GMSPolyline] = response.routes.map({ route in
var coordinates = CLLocationCoordinate2D
route.polyline.getCoordinates(
&coordinates,
range: NSRange(location: 0, length: route.polyline.pointCount)
)
let polyline = Polyline(coordinates: coordinates)
let encodedPolyline: String = polyline.encodedPolyline
let path = GMSPath(fromEncodedPath: encodedPolyline)
return GMSPolyline(path: path)
})
return polylines
}
`

Render GMSPolyline

Use GMSStyleSpans to style

`swift
func show(polylines: [GMSPolyline]) {
polylines.forEach { polyline in
let strokeStyles = [
GMSStrokeStyle.solidColor(R.color.primary),
GMSStrokeStyle.solidColor(.clear)
]
let strokeLengths = [
NSNumber(value: 10),
NSNumber(value: 6)
]
if let path = polyline.path {
polyline.spans = GMSStyleSpans(path, strokeStyles, strokeLengths, .rhumb)
}
polyline.strokeWidth = 3
polyline.map = mapView
}

self.polylines = polylines

}
`

Read more

Original post https://github.com/onmyway133/blog/issues/290

Top comments (0)