Question

I've been looking at Apple's iOS Class Reference documentation, and am unfortunately none the wiser. I have downloaded their sample code KMLViewer but they've overcomplicated it... All I really want to know is how to generate a path and add it to the MKMapView. The documentation talks of using a CGPathRef, but doesn't really explain how.

Was it helpful?

Solution

Here's how to generate a path and add it as an overlay to an MKMapView. I'm going to use an MKPolylineView, which is a subclass of MKOverlayPathView and shields you from having to refer to any CGPath since you instead create an MKPolyline (containing the data of the path) and use that to create the MKPolylineView (the visual representation of the data on the map).

The MKPolyline has to be created with a C array of points (MKMapPoint), or a C array of coordinates (CLLocationCoordinate2D). It's a shame that MapKit doesn't use more advanced data structures such as NSArray, but so be it! I'm going to assume that you have an NSArray or NSMutableArray of CLLocation objects to demonstrate how to convert to a C array of data suitable for the MKPolyline. This array is called locations and how you fill it would be determined by your app - e.g. filled in by processing touch locations by the user, or filled with data downloaded from a web service etc.

In the view controller that is in charge of the MKMapView:

int numPoints = [locations count];
if (numPoints > 1)
{
    CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
    for (int i = 0; i < numPoints; i++)
    {
         CLLocation* current = [locations objectAtIndex:i];
         coords[i] = current.coordinate;
    }

    self.polyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
    free(coords);

    [mapView addOverlay:self.polyline];
    [mapView setNeedsDisplay];
}

Note that self.polyline is declared in the .h as:

@property (nonatomic, retain) MKPolyline* polyline;

This view controller should also implement the MKMapViewDelegate method:

- (MKOverlayView*)mapView:(MKMapView*)theMapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineView* lineView = [[[MKPolylineView alloc] initWithPolyline:self.polyline] autorelease];
    lineView.fillColor = [UIColor whiteColor];
    lineView.strokeColor = [UIColor whiteColor];
    lineView.lineWidth = 4;
    return lineView;
}

You can play with the fillColor, strokeColor and lineWidth properties to ensure that they are appropriate for your app. I've just gone with a simple, moderately wide plain white line here.

If you want to remove the path from the map, e.g. to update it with some new coordinates, then you would do:

[mapView removeOverlay:self.polyline];
self.polyline = nil;

and then repeat the above process to create a new MKPolyline and add it to the map.

Although on first glance MapKit can look a bit scary and complex, it can be easy to do some things as illustrated in this example. The only scary bit - for non-C programmers at least - is the use of malloc to create a buffer, copy the CLLocationCoordinates into it using array syntax, and then freeing the memory buffer afterwards.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top