iOS MapKit connect multiple points on map over roads

I’m using this code to connect pins(points on map) with polyline:

CLLocationCoordinate2D coordinates[allLocations.count];
    int i = 0;
    for (locHolder *location in allLocations) {
        coordinates[i] = CLLocationCoordinate2DMake([location.lat floatValue], [location floatValue]);
        i++;
    }
    MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coordinates count:[allLocations count]];
    self->polyline = polyline;
    [self.mapView addOverlay:self->polyline level:MKOverlayLevelAboveRoads];

But this code connects them over-the-air(ignoring roads), is it possible to connect multiple CLLocationCoordinate2D locations with polyline that follows roads?

  • How to track a user's location and display the path travelled using Google Maps ios SDK
  • Wrong polyline drawing on map with Google Maps SDK
  • Detect tap on GMSPolyline in Swift?
  • Multiple MKPolyline on MKMapView iOS6
  • Find nearest point in polyline/path
  • How add polyline in mapView
  • **
    And a shor sub question,
    Is there any difference in performance between [allLocations count] and allLocations.count.

    Thanks.

    Solutions Collect From Internet About “iOS MapKit connect multiple points on map over roads”

    In these days I’ve came across with the same problem, and looking for answers here and there, I found this answer from Rob very useful for this case.

    First, supose you have in your MapViewController, an array of objects containing an origin an a destination, each one being of type CLLocationCoordinate2D

    In your MapViewController.h

    @property (nonatomic, strong) NSArray *locations;
    

    Then, in the implementation, populate that array with some data that goes like this:

    _locations = [NSArray arrayWithObjects:
        [RouteObject routeWithOrigin:CLLocationCoordinate2DMake(-23.595571, -46.684408) destination:CLLocationCoordinate2DMake(-23.597886, -46.673950)],
        [RouteObject routeWithOrigin:CLLocationCoordinate2DMake(-23.597886, -46.673950) destination:CLLocationCoordinate2DMake(-23.597591, -46.666805)],
        [RouteObject routeWithOrigin:CLLocationCoordinate2DMake(-23.597591, -46.666805) destination:CLLocationCoordinate2DMake(-23.604061, -46.662728)], nil];
    

    Now that you have your array of origin and destinations, you can start drawing a route between them (from A to B, from B to C and from C to D).

    Add a button and then connect an IBAction so in that method you are going to do de magic.

    - (IBAction)btnDirectionsPressed:(id)sender {
        [self enableUI:NO];    // This method enables or disables all the UI elements that interact with the user
    
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);     // Create the semaphore    
    
        __block NSMutableArray *routes = [[NSMutableArray alloc] init];         // Arrays to store MKRoute objects and MKAnnotationPoint objects, so then we can draw them on the map
        __block NSMutableArray *annotations = [[NSMutableArray alloc] init];
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            for (RouteObject *routeObject in _locations) {
                MKDirectionsRequest *directionsRequest = [MKDirectionsRequest new];
                [directionsRequest setTransportType:MKDirectionsTransportTypeAutomobile];
                [directionsRequest setSource:[routeObject originMapItem]];
                [directionsRequest setDestination:[routeObject destinationMapItem]];
                [directionsRequest setRequestsAlternateRoutes:NO];
    
                MKDirections *direction = [[MKDirections alloc] initWithRequest:directionsRequest];
    
                // For each object in the locations array, we request that route from its origin and its destination
                [direction calculateDirectionsWithCompletionHandler: ^(MKDirectionsResponse *response, NSError *error) {   
                    if (error) {
                        NSLog(@"There was an error getting your directions");
                        return;
                    }
    
                    MKRoute *route = [response.routes firstObject];   
                    [routes addObject:route];
                    [annotations addObject:[routeObject destinationAnnotation]];
    
                    dispatch_semaphore_signal(semaphore);    // Send the signal that one semaphore is ready to consume
                }];
            }
        });
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            for (int i = 0; i < _locations.count; i++) {
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);    // Wait until one semaphore is ready to consume
    
                dispatch_async(dispatch_get_main_queue(), ^{    // For each element, dispatch to the main queue to draw route and annotation corresponding to that location
                    MKRoute *route = routes[i];
                    [self.mapView addOverlay:route.polyline];
                    [self.mapView addAnnotation:annotations[i]];
                });
            }
    
            dispatch_async(dispatch_get_main_queue(), ^{   // Finally, dispatch to the main queue enabling elements and resizing map to show all the annotations
                [self enableUI:YES];
                [self fitRegionToRoutes];
            });
        });
    }
    

    Hope this help!

    Joel.