que tenían la misma tarea y aquí es cómo lo resuelvo:
NOTA: este código sólo funcionará a partir de iOS7
Añadir una superposición al mapa, en algún lugar de su controlador de vista:
MyMapOverlay *overlay = [[MyMapOverlay alloc] initWithCoordinate:coordinate];
[self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels];
En los métodos MKMapViewDelegate escribir a continuación:
- (MKOverlayRenderer *)mapView:(MKMapView *)map rendererForOverlay:(id<MKOverlay>)overlay {
/// we need to draw overlay on the map in a way when everything except the area in radius of 500 should be grayed
/// to do that there is special renderer implemented - NearbyMapOverlay
if ([overlay isKindOfClass:[NearbyMapOverlay class]]) {
MyMapOverlayRenderer *renderer = [[MyMapOverlayRenderer alloc] initWithOverlay:overlay];
renderer.fillColor = [UIColor whateverColor];/// specify color which you want to use for gray out everything out of radius
renderer.diameterInMeters = 1000;/// choose whatever diameter you need
return renderer;
}
return nil;
}
El MyMapOverlay sí mismo debería ser algo como sigue:
@interface MyMapOverlay : NSObject<MKOverlay>
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end
@implementation MyMapOverlay
@synthesize coordinate = _coordinate;
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
self = [super init];
if (self) {
_coordinate = coordinate;
}
return self;
}
- (MKMapRect)boundingMapRect {
return MKMapRectWorld;
}
@end
Y el MyMapOverlayRenderer:
@interface MyMapOverlayRenderer : MKOverlayRenderer
@property (nonatomic, assign) double diameterInMeters;
@property (nonatomic, copy) UIColor *fillColor;
@end
@implementation MyMapOverlayRenderer
/// this method is called as a part of rendering the map, and it draws the overlay polygon by polygon
/// which means that it renders overlay by square pieces
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context {
/// main path - whole area
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(mapRect.origin.x, mapRect.origin.y, mapRect.size.width, mapRect.size.height)];
/// converting to the 'world' coordinates
double radiusInMapPoints = self.diameterInMeters * MKMapPointsPerMeterAtLatitude(self.overlay.coordinate.latitude);
MKMapSize radiusSquared = {radiusInMapPoints, radiusInMapPoints};
MKMapPoint regionOrigin = MKMapPointForCoordinate(self.overlay.coordinate);
MKMapRect regionRect = (MKMapRect){regionOrigin, radiusSquared}; //origin is the top-left corner
regionRect = MKMapRectOffset(regionRect, -radiusInMapPoints/2, -radiusInMapPoints/2);
// clamp the rect to be within the world
regionRect = MKMapRectIntersection(regionRect, MKMapRectWorld);
/// next path is used for excluding the area within the specific radius from current user location, so it will not be filled by overlay fill color
UIBezierPath *excludePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(regionRect.origin.x, regionRect.origin.y, regionRect.size.width, regionRect.size.height) cornerRadius:regionRect.size.width/2];
[path appendPath:excludePath];
/// setting overlay fill color
CGContextSetFillColorWithColor(context, self.fillColor.CGColor);
/// adding main path. NOTE that exclusionPath was appended to main path, so we should only add 'path'
CGContextAddPath(context, path.CGPath);
/// tells the context to fill the path but with regards to even odd rule
CGContextEOFillPath(context);
}
Como resultado, usted tendrá exactamente la misma vista como la de la imagen de la izquierda que se ha escrito en la pregunta .
¿Puede usted por favor, sugiera cómo o por qué ha escrito usted en el método drawRect? – HarshIT
Pintar en un mapa completo también hará que el área entre pintada, pero él no la quiere. ¿Cómo se acepta la respuesta? –