When displaying directions on the built-in Maps.app on the iPhone you can \"select\" one of the usually 3 route alternatives that are displayed by tapping on it. I wan\'t to
@Rashwan L : Updated his answer to Swift 4.2
let map = MKMapView()
let mapTap = UITapGestureRecognizer(target: self, action: #selector(mapTapped(_:)))
map.addGestureRecognizer(mapTap)
@objc private func mapTapped(_ tap: UITapGestureRecognizer) {
if tap.state == .recognized && tap.state == .recognized {
// Get map coordinate from touch point
let touchPt: CGPoint = tap.location(in: skyMap)
let coord: CLLocationCoordinate2D = skyMap.convert(touchPt, toCoordinateFrom: skyMap)
let maxMeters: Double = meters(fromPixel: 22, at: touchPt)
var nearestDistance: Float = MAXFLOAT
var nearestPoly: MKPolyline? = nil
// for every overlay ...
for overlay: MKOverlay in skyMap.overlays {
// .. if MKPolyline ...
if (overlay is MKPolyline) {
// ... get the distance ...
let distance: Float = Float(distanceOf(pt: MKMapPoint(coord), toPoly: overlay as! MKPolyline))
// ... and find the nearest one
if distance < nearestDistance {
nearestDistance = distance
nearestPoly = overlay as? MKPolyline
}
}
}
if Double(nearestDistance) <= maxMeters {
print("Touched poly: \(nearestPoly) distance: \(nearestDistance)")
}
}
}
private func distanceOf(pt: MKMapPoint, toPoly poly: MKPolyline) -> Double {
var distance: Double = Double(MAXFLOAT)
for n in 0.. 1.0 {
ptClosest = ptB
}
else {
ptClosest = MKMapPoint(x: ptA.x + u * xDelta, y: ptA.y + u * yDelta)
}
distance = min(distance, ptClosest.distance(to: pt))
}
return distance
}
private func meters(fromPixel px: Int, at pt: CGPoint) -> Double {
let ptB = CGPoint(x: pt.x + CGFloat(px), y: pt.y)
let coordA: CLLocationCoordinate2D = skyMap.convert(pt, toCoordinateFrom: skyMap)
let coordB: CLLocationCoordinate2D = skyMap.convert(ptB, toCoordinateFrom: skyMap)
return MKMapPoint(coordA).distance(to: MKMapPoint(coordB))
}