I'm using MapKit to display directions between locations, and I'm looking for a way to add an annotation that works similarly to the route annotation in the Apple Maps app, where annotations are showing each route's travel time (as shown in the image below). I am already drawing the directions correctly, the problem at hand is how to calculate a pair of coordinates along the route. That is, where to drop the annotation.
I thought about somehow using the MKDirection
(which contains complete directions, step by step) but I am not sure how I would generate a pair of coordinates that are somewhere in the middle of the route.
I have not been able to find any kind of support for this in the MapKit documentation. Any ideas?
This is how I generate the route and display it.
- (void)generateRoute {
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = self.destinationMapItem;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
// Handle Error
} else {
[self showRoute:response];
}
}];
}
- (void)showRoute:(MKDirectionsResponse *)response {
[self.mapView removeOverlays:self.mapView.overlays];
for (MKRoute *route in response.routes)
{
[self.mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
}
[self fitRegionToRoute];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor blueColor];
renderer.alpha = 0.7;
renderer.lineWidth = 4.0;
return renderer;
}
If you want to know the middle for swift you can use the following code :
MKCoordinateForMapPoint(route.polyline.points()[route.polyline.pointCount/2])
Exemple of use :
directions.calculateDirectionsWithCompletionHandler ({
(response: MKDirectionsResponse?, error: NSError?) in
if error == nil {
self.showRoute(response!)
}
else{
print("some error")
}
})
func showRoute(response:MKDirectionsResponse){
for route in response.routes {
self.map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
self.map.setCenterCoordinate(route.polyline.coordinate, animated: true)
self.map.setRegion(MKCoordinateRegionMakeWithDistance(route.polyline.coordinate, route.distance*0.75, route.distance*0.75), animated: true)
let routeAnnotation = MKPointAnnotation()
routeAnnotation.coordinate = MKCoordinateForMapPoint(route.polyline.points()[route.polyline.pointCount/2])
map.addAnnotation(routeAnnotation)
}
}
Questioner's edit:
Finally made it work with the help of this answer. I added this to the code below, where it says Here do the magic:
MKMapPoint middlePoint = route.polyline.points[route.polyline.pointCount/2];
[self createAndAddAnnotationForCoordinate:MKCoordinateForMapPoint(middlePoint)];
Original answer:
I don't know whether this will work or not. Just my idea on your question.
I guess you would have created the routes as following (Check my inline comments)
MKDirectionsRequest *request =
[[MKDirectionsRequest alloc] init];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = _destination;
request.requestsAlternateRoutes = NO;
MKDirections *directions =
[[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
// Handle error
} else {
for (MKRoute *route in response.routes)
{
[_routeMap addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
//Here do the magic
//MKPolyline confronts to MKOverlay so you can get the coordinate like
//route.polyline.coordinate once you get the coordinate then you can build
//a annotation. A annotation is nothing but a coordinate with some title.
//According to MKOverlay coordinate property it justs gives you the
//center point of the overlay area
[self createAndAddAnnotationForCoordinate:route.polyline.coordinate]
}
}
}];
Adding Annotation
-(void) createAndAddAnnotationForCoordinate : (CLLocationCoordinate2D) coordinate{
MyAnnotation* annotation= [[MyAnnotation alloc] init];
annotation.coordinate = coordinate;
annotation.title = @"Any Title";
annotation.subtitle = @"Any Subtitle";
[yourMap addAnnotation: annotation];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With