Plotting a users route taken on a map using MKPolyline
core-location, location, mapkit, mkpolyline, objective-c
Solution
You should just create a `NSMutableArray` to hold your locations that you instantiate in `viewDidLoad`. So have `didUpdateToLocation` (or, if supporting iOS 6 and higher, you should use `didUpdateToLocations`) simply add a location to an array, then build a `MKPolyline` from that array, add that `MKPolyline` to the map, and then remove the old `MKPolyline`. Or you could add all of the line segments as individual `MKPolyline` objects, but the idea is the same, create a model to hold you locations (e.g. a `NSMutableArray`) and then add the appropriate `MKPolyline` object(s) to the map view.
For example, you could do something like:
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
if (location.horizontalAccuracy < 0)
return;
[self.locations addObject:location];
NSUInteger count = [self.locations count];
if (count > 1) {
CLLocationCoordinate2D coordinates[count];
for (NSInteger i = 0; i < count; i++) {
coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
}
MKPolyline *oldPolyline = self.polyline;
self.polyline = [MKPolyline polylineWithCoordinates:coordinates count:count];
[self.mapView addOverlay:self.polyline];
if (oldPolyline)
[self.mapView removeOverlay:oldPolyline];
}
}
And remember to specify how the map is to draw the `MKPolyline`. So set your view controller to be a the `delegate` of your `MKMapView`, and you can then do something like the following:
#pragma mark - MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
renderer.lineWidth = 3;
return renderer;
}
return nil;
}
// for iOS versions prior to 7; see `rendererForOverlay` for iOS7 and later
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineView *overlayView = [[MKPolylineView alloc] initWithPolyline:overlay];
overlayView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
overlayView.lineWidth = 3;
return overlayView;
}
return nil;
}
Problem
I'm quite new to Objective-c. In my app, I'm trying to plot the users taken route onto a map. Here is what I have so far that just gets the users current location: ``` #import "StartCycleViewController.h" #import "CrumbPath.h" @interface StartCycleViewController () @property (nonatomic, strong) CLLocationManager *locationManager; @property (nonatomic, strong) IBOutlet MKMapView *map; @property (nonatomic, strong) UIView *containerView; @end @implementation StartCycleViewController @synthesize cycleLocation = _cycleLocation; @synthesize currentCycleLocation = _currentCycleLocation; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self startCycleLocation]; _containerView = [[UIView alloc] initWithFrame:self.view.bounds]; [self.view addSubview:self.containerView]; [self.containerView addSubview:self.map]; // Do any additional setup after loading the view. } - (void)dealloc { self.locationManager.delegate = nil; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - startCycleLocation - (void)startCycleLocation{ if (!_cycleLocation){ _cycleLocation = [[CLLocationManager alloc]init]; _cycleLocation.desiredAccuracy = kCLLocationAccuracyBestForNavigation; _cycleLocation.distanceFilter = 10; _cycleLocation.delegate = self; } [_cycleLocation startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"didUpdateToLocation: %@", newLocation); CLLocation *currentLocation = newLocation; if (currentLocation != nil) { self.longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude]; self.latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude]; } } - (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"%@",error); if ( [error code] != kCLErrorLocationUnknown ){ [self stopLocationManager]; } } - (void) stopLocationManager { [self.cycleLocation stopUpdatingLocation]; } @end ``` I've had a look around online and gather that I should use `MKPolyline`and give it coordinates. But I'm just not sure how I would store the locations and then send them use `MKPolyline` to plot the points, continuously while the app is running.