Pregunta

Here's the code. Its pretty straight forward. I'm making a path for someone who is walking. So, here's the code for my ViewController.m file :

#import "ViewController.h"

@interface ViewController ()

@property BOOL firstTime;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.mapView setDelegate:self];
    [self.mapView setShowsUserLocation:YES];
    [self.mapView setMapType:MKMapTypeHybrid];

    [self setLocationManager:[[CLLocationManager alloc] init]];
    [self.locationManager setDelegate:self];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager startUpdatingLocation];

    self.index = 0;

    self.firstTime = YES;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    if(self.firstTime)
    {
        CLLocation *startingLocation = [locations objectAtIndex:0];
        self.startingPointCooridinates = startingLocation.coordinate;
        self.index++;

        MKPointAnnotation *startingPointAnnotation = [[MKPointAnnotation alloc] init];
        startingPointAnnotation.title = @"Starting Point";
        startingPointAnnotation.coordinate = startingLocation.coordinate;

        [self.mapView addAnnotation:startingPointAnnotation];

        self.firstTime = false;
    }

    [self.locations addObject:[locations objectAtIndex:0]];

    CLLocationCoordinate2D coordinates[[self.locations count]];
    for(int i = 0; i < self.locations.count; i++)
    {
        CLLocation *currentLocation = [locations objectAtIndex:i];
        coordinates[i] = currentLocation.coordinate;
    }

    MKPolyline *pathPolyline = [MKPolyline polylineWithCoordinates:coordinates count:self.locations.count];
    [self.mapView addOverlay:pathPolyline];
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    if([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineRenderer *polylineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
        polylineRenderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
        polylineRenderer.strokeColor = [[UIColor redColor] colorWithAlphaComponent:0.7];
        polylineRenderer.lineWidth = 2.0;
        return polylineRenderer;
    }
    else
    {
        return  nil;
    }
}

Now, only the annotation is showing and there isn't any MKPolyline showing up. What am I doing wrong ? Thanks.

¿Fue útil?

Solución

  1. As mentioned in the comments, your locations array is never allocated and initialized so it's nil and calls to it (like addObject) do nothing and so the polyline never gets any coordinates added to it (and so it doesn't show).

    In viewDidLoad, before starting the CLLocationManager, alloc and init the array:

    self.locations = [NSMutableArray array];
    
  2. Another issue you will encounter is with this line in didUpdateLocations in the for loop:

    CLLocation *currentLocation = [locations objectAtIndex:i];
    

    Here, locations (without the self.) refers to the delegate method's local parameter variable and not your locations class-instance-level property variable. The compiler must be warning you about this with a message like "Local declaration of 'locations' hides instance variable".

    In this case, the warning is critical. What you really mean to do here is reference the locations property variable where you are storing the user's complete trail of coordinates and not the local variable which only has the last x un-reported locations (usually only 1 object).

    So that line should be changed to:

    CLLocation *currentLocation = [self.locations objectAtIndex:i];
    

    It would be better if you just used a different name than locations to avoid these problems.

  3. As also mentioned in the comments, since you are adding an overlay with the user's complete trail of motion every time the user moves, you need to remove the previous overlay first. Otherwise, you will needlessly be adding multiple overlays to the map since the last overlay covers the entire motion. The previous overlays are not obviously visible since they have the same coordinates, the same color, and the same line width. So before calling addOverlay, the simplest thing to do is call removeOverlays with map's current list of overlays:

    //remove any previous overlays first...
    [self.mapView removeOverlays:mapView.overlays];
    
    //now add overlay with the updated trail...
    [self.mapView addOverlay:pathPolyline];
    
  4. A minor point not affecting the display is that setting fillColor for a polyline has no effect. You only need to set strokeColor which the code is doing. You can remove the call to set fillColor.

  5. Finally, you may be interested in seeing Apple's Breadcrumb sample app. Their version uses a custom overlay which can be dynamically updated without having to remove and add overlays every time there's a change or addition.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top