I'm having trouble getting an MKPolygonRenderer to appear over my map. I have a class MapViewController
that contains an MKMapView
, and create CustomMapOverlay
instances to render over the MKMapView
.
MapViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
}
// ...
// Later, I retrieve some models and generate CustomMapOverlay instances from them...
for (Model *model in models) {
CustomMapOverlay *customMapOverlay = [[CustomMapOverlay alloc] initWithModel:model];
[self.mapView addOverlay:customMapOverlay];
}
// ...
// Implement MKMapViewDelegate protocol
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
MKPolygonRenderer *polygonRenderer = [[MKPolygonRenderer alloc] initWithOverlay:overlay];
polygonRenderer.lineWidth = 2;
polygonRenderer.strokeColor = [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:1.0];
polygonRenderer.fillColor = [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:0.5];
return polygonRenderer;
}
CustomMapOverlay.m:
@implementation CustomMapOverlay
// Required by MKOverlay protocol
@synthesize coordinate,
boundingMapRect;
- (instancetype)initWithModel:(Model *)model {
coordinate = CLLocationCoordinate2DMake(model.latitude, model.longitude);
double radiusInPoints = MKMapPointsPerMeterAtLatitude(model.latitude) * model.radius;
boundingMapRect = MKMapRectMake(model.latitude, model.longitude, radiusInPoints, radiusInPoints);
return self;
}
@end
mapView:rendererForOverlay
is getting called, and inspecting the overlay
in the debugger I see a coordinate
within the map's current on-screen bounds and what seems like a reasonable boundingMapRect
(though I'm not sure what "map points" are, I'm trusting that MKMapPointsPerMeterAtLatitude
method to do what it says it does).
But, no polygons appear on the map.
UPDATE:
I realize now that I'm attempting to render polygons without creating them. Instead of CustomMapOverlay
, then, I'm now generating MKPolygon
overlays like this:
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(model.latitude, model.longitude);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(centerCoordinate, model.radius, model.radius);
int numCoords = 4;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numCoords);
coords[0] = CLLocationCoordinate2DMake((region.center.longitude - 0.5*region.span.longitudeDelta), (region.center.latitude + 0.5*region.span.latitudeDelta));
coords[1] = CLLocationCoordinate2DMake((region.center.longitude + 0.5*region.span.longitudeDelta), (region.center.latitude + 0.5*region.span.latitudeDelta));
coords[2] = CLLocationCoordinate2DMake((region.center.longitude + 0.5*region.span.longitudeDelta), (region.center.latitude - 0.5*region.span.latitudeDelta));
coords[3] = CLLocationCoordinate2DMake((region.center.longitude - 0.5*region.span.longitudeDelta), (region.center.latitude - 0.5*region.span.latitudeDelta));
MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coords count:numCoords];
free(coords);
[self.mapView addOverlay:polygon];
However, now mapView:rendererForOverlay
is no longer getting called at all.
In the updated code which creates an MKPolygon
, the coordinates in the coords
array are backwards. For example, this line:
coords[0] = CLLocationCoordinate2DMake(
(region.center.longitude - 0.5*region.span.longitudeDelta),
(region.center.latitude + 0.5*region.span.latitudeDelta));
should be:
coords[0] = CLLocationCoordinate2DMake(
(region.center.latitude + 0.5*region.span.latitudeDelta,
(region.center.longitude - 0.5*region.span.longitudeDelta));
In the CLLocationCoordinate2DMake
function, the first parameter is latitude, then longitude.
Because the coordinates are backwards, they may either be completely invalid or in the wrong location.
The rendererForOverlay
delegate method will only get called if the overlay's boundingMapRect
(which MKPolygon
will automatically define based on the given coordinates) is in the currently displayed area of the map. But if the coordinates are invalid or in the wrong location, the boundingMapRect
will be invalid as well.
CustomMapOverlay
, there were at least these two issues:
initWithModel
method doesn't call [super init]
(assuming it's an NSObject
subclass).boundingMapRect
is not calculated correctly. The MKMapRectMake
function takes MKMapPoint
values but the code is passing latitude and longitude in degrees. An MKMapPoint
is not the same as a CLLocationCoordinate2D
. You can convert a CLLocationCoordinate2D
to an MKMapPoint
using the MKMapPointForCoordinate
function. See MKMapPointForCoordinate returning invalid coordinates and Map Coordinate Systems in the documentation for some more info.