Domanda

So I want to display where my app's user walked on a MKMapView, I collect datas with the following code :

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    
    // calc. distance walked
    CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
    self.totalMetters += meters;
    [[self labelDistance] setText:[self formatDistanceIntoString:self.totalMetters]];
    
   //  create another annotation
    MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
    annotation.coordinate = newLocation.coordinate;
            
    // Also add to our map so we can remove old values later
    [self.locations addObject:annotation];
    
    // Remove values if the array is too big
    while (self.locations.count > 100)
    {
        annotation = [self.locations objectAtIndex:0];
        [self.locations removeObjectAtIndex:0];
        
        // Also remove from the map
        [self.map removeAnnotation:annotation];
    }

Once it's finished, I call my draw method :

[self drawRoute];

Which contains the following :

- (void)drawRoute {
    
    NSLog(@"drawRoute");
    NSInteger pointsCount = self.locations.count;
    
    CLLocationCoordinate2D pointsToUse[pointsCount];
    
    for(int i = 0; i < pointsCount; i++) {
        MKPointAnnotation *an = [self.locations objectAtIndex:i];
        pointsToUse[i] = CLLocationCoordinate2DMake(an.coordinate.latitude,an.coordinate.latitude);
    }
    
    MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:pointsToUse count:pointsCount];
    
    [self.map addOverlay:myPolyline];
}

Finally my mapView delegate :

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
    NSLog(@"route");
    if ([overlay isKindOfClass:MKPolyline.class]) {
        MKPolylineView *lineView = [[MKPolylineView alloc] initWithOverlay:overlay];
        lineView.strokeColor = [UIColor greenColor];
        
        return lineView;
    }
    return nil;
}

Obviously my controller is MKMapView Delegate conform

@interface NewWalkViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> 

And the mapView in the Storyboard is linked to the controller (outlet and delegate)

I use the "bike road" debug tool and there is the output :

2014-01-25 20:27:30.132 The walking dog[2963:70b] new location : 37.330435

2014-01-25 20:27:30.133 The walking dog[2963:70b] drawRoute

As I can see the method for drawing the overlay is never called, and I don't have a single clue how to fix it.

È stato utile?

Soluzione

The main problem is that in drawRoute, this line is passing latitude for both parameters to CLLocationCoordinate2DMake:

pointsToUse[i] = CLLocationCoordinate2DMake
                     (an.coordinate.latitude,an.coordinate.latitude);

This results in the line being drawn in a different part of the world than where the actual an.coordinate is. For example, if an.coordinate is 37,-122 (somewhere near San Francisco), the line is being drawn instead at 37,37 (somewhere in southern Turkey).

Since you are not actually positioning the map at the wrong location (you are looking for the line at the "right" location), viewForOverlay is never called because the map only calls it when it's possible that the overlay will be visible.


Change that line to:

pointsToUse[i] = CLLocationCoordinate2DMake
                     (an.coordinate.latitude,an.coordinate.longitude);

or simply:

pointsToUse[i] = an.coordinate;


As James Frost mentions in the comments, as of iOS 7, you should be using rendererForOverlay instead of viewForOverlay though the map view will still call viewForOverlay in iOS 7 if rendererForOverlay has not been implemented. Though this isn't preventing your overlay from displaying in the current case, you should implement the new delegate method as well as the old one (if the iOS 7 app will also be running on iOS 6 or earlier).


Another important but unrelated issue is that you are unnecessarily creating multiple, overlapping overlays. In drawRoute, since the overlay you are creating includes all the locations, you should remove any existing overlays before adding the new one. Otherwise, the map ends up with an overlay for location 0 to 1, an overlay for location 0 to location 2, an overlay for location 0 to location 3, etc. The previous overlays are not obviously visible since they have the same color and line width. Before the addOverlay line, put:

[self.map removeOverlays:self.map.overlays];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top