Search code examples
iosmkmapviewmkoverlaymkmapviewdelegate

viewforoverlay never gets called


This is driving me nuts. I've been through all the posts on stackoveflow, but nothing fits the bill. I am trying to add a simple polyline (i.e. not a custom overlay) as an overlay to my MKMapView. The viewForOverlay method on the delegate never gets called. The map delegate is correctly called for every other delegate function. Here is the code from the viewForOverlay method:

//maanges the overlay
- (MKOverlayView *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay{

    NSLog(@"does it ask for the overlay view?");

    MKOverlayView *overlayView = nil;

    return overlayView;
}

Here is the code where I construct the polyline and add it to the map:

    MKPolyline *thePolyline = [MKPolyline polylineWithPoints:pts count:[arrOfPoints count]];

    [thePolyline setTitle:@"line"];

    [mapView addOverlay:thePolyline];

The polyline does in fact have my collection of points (about 1000), so I don't think the issue is there. Am I missing some required property or some other implementation on the map view?

EDIT Shows the code for polyline MKMapPoint generation:

I use an xml file with about 1100 points to generate the polyline as part of an appConfig process. I read and parse the file with NSXMLParser and NSXMLParserDelegate respectively. Here is the code that generates the points (from the foundCharacters method in the NSXMLParserDelegate protocol):

//NSXMLParserDelegate methods...
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{

    if(POINT){
        NSArray *arr = [string componentsSeparatedByString:@","];

        MKMapPoint pt = MKMapPointMake([[arr objectAtIndex:1]doubleValue], [[arr objectAtIndex:0]doubleValue]);

        MapPointObject *thePoint = [[MapPointObject alloc] init];
        thePoint.mapPoint = pt;

        //gives the mkmappoint to the array of points.
        [arrOfPoints addObject:thePoint];

        [thePoint release];
    }
}

and here is the where the points actually generate the MKPolyline and gives it to the mapView (from the didEndElement method on the NSXMLParserDelegate protocol):

   if([elementName isEqualToString:@"appConfig"]){
        MKMapPoint *pts = malloc([arrOfPoints count] * sizeof(MKMapPoint));

        for(int i = 0; i <= [arrOfPoints count] - 1; i++){
            MapPointObject *pointObject = [arrOfPoints objectAtIndex:i];
            pts[i] = pointObject.mapPoint;
        }

        MKPolyline *thePolyline = [MKPolyline polylineWithPoints:pts count:[arrOfPoints count]];
        [thePolyline setTitle:@"line"];

        //adding the polyline to the model's mapview
        Model *theModel = [Model sharedModel];

        [theModel.mapView setVisibleMapRect:thePolyline.boundingMapRect animated:YES];
        [theModel.mapView addOverlay:thePolyline];

        free(pts);
    }

The point count property on the MKPolyline does in fact say that there are 1100 points in it.

EDIT: sample XML values:

<appConfig>
<point>-94.847587,38.977967</point>
<point>-94.844111,38.977978</point>
<point>-94.844108,38.977369</point>
<point>-94.844003,38.977369</point>
<point>-94.843955,38.974886</point>

Solution

  • The xml file contains coordinates (latitude and longitude) values. These coordinate values are not the same thing as MKMapPoint values (which are the map view's x,y projection of the lat/long onto the flat map).

    You should be storing coordinates and not MKMapPoint values (which you are).

    So instead of using MKMapPoint and polylineWithPoints, use CLLocationCoordinate2D and polylineWithCoordinates.

    In the xml parser method, create and store a CLLocationCoordinate2D using CLLocationCoordinate2DMake.

    The pts array should be of type CLLocationCoordinate2D * and when doing the malloc, use sizeof(CLLocationCoordinate2D).

    Then call polylineWithCoordinates instead of polylineWithPoints.


    By the way, you'll also need to actually return a non-nil overlay view in viewForOverlay after making the above changes otherwise you still won't see the line:

    MKPolylineView *polylineView = [[[MKPolylineView alloc] initWithPolyline:overlay] autorelease];
    polylineView.strokeColor = [UIColor redColor];
    polylineView.lineWidth = 2.0;
    return polylineView;