Drawing circle in MKMapView as we see in reminders in iPhone. Here have pasted some code which works as below.
Reference
http://stackoverflow.com/a/31050127
I used class names are below
1. MyMapOverlay.h
2. MyMapOverlayRenderer.h
3. ViewController.h
MyMapOverlay.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface MyMapOverlay : NSObject<MKOverlay>
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end
MyMapOverlay.m
#import "MyMapOverlay.h"
@implementation MyMapOverlay
@synthesize coordinate = _coordinate;
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
self = [super init];
if (self) {
_coordinate = coordinate;
}
return self;
}
- (MKMapRect)boundingMapRect {
return MKMapRectWorld;
}
@end
MyMapOverlayRenderer.h
#import <MapKit/MapKit.h>
@interface MyMapOverlayRenderer : MKOverlayRenderer
@property (nonatomic, assign) double diameterInMeters;
@property (nonatomic, assign) MKMapRect circleRect;
@property (nonatomic, copy) UIColor *fillColor;
@end
MyMapOverlayRenderer.m
#import "MyMapOverlayRenderer.h"
@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(_circleRect.origin.x, _circleRect.origin.y, _circleRect.size.width, _circleRect.size.height) cornerRadius:_circleRect.size.width];
[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);
}
@end
ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface ViewController : UIViewController<MKMapViewDelegate>
@property(nonatomic,weak)IBOutlet MKMapView *map;
@end
ViewController.m
#import "ViewController.h"
#import "MKMapView+ZoomLevel.h"
#import "MyMapOverlay.h"
#import "MyMapOverlayRenderer.h"
@interface ViewController ()
{
MKCircle *circle,*circle2;
}
@end
@implementation ViewController
@synthesize map;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
map.delegate=self;
[self centerMap];
}
-(void)centerMap
{
CLLocationCoordinate2D center;
center.latitude = 12.8421;
center.longitude = 77.6631;
double retVal=1609.344f;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center,10000 ,10000);
[map setRegion:[map regionThatFits:region] animated:YES];
CLLocationDistance fenceDistance = retVal;
CLLocationCoordinate2D circleMiddlePoint = CLLocationCoordinate2DMake(center.latitude, center.longitude);
circle = [MKCircle circleWithCenterCoordinate:circleMiddlePoint radius:fenceDistance];
[map addOverlay: circle];
MyMapOverlay *overlay = [[MyMapOverlay alloc] initWithCoordinate:center];
[self.map addOverlay:overlay level:MKOverlayLevelAboveLabels];
}
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(@"zoom level =%f",[map getZoomLevel]);
CLLocationCoordinate2D center;
center.latitude = 12.8421;
center.longitude = 77.6631;
if([map getZoomLevel]>30)
{
[mapView setCenterCoordinate:center zoomLevel:15 animated:NO];
}
}
- (MKCircleRenderer *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MyMapOverlay class]]) {
MyMapOverlayRenderer *renderer = [[MyMapOverlayRenderer alloc] initWithOverlay:overlay];
renderer.fillColor = [[UIColor blackColor] colorWithAlphaComponent:0.1];/// specify color which you want to use for gray out everything out of radius
renderer.circleRect=circle.boundingMapRect;
return (MKCircleRenderer *)renderer;
}
MKCircleRenderer *circleView = [[MKCircleRenderer alloc] initWithOverlay:overlay];
circleView.strokeColor = [UIColor yellowColor];
circleView.lineWidth=2.0;
return circleView;
}
-(IBAction)btnPlusClick:(id)sender
{
MKCoordinateRegion region;
MKCoordinateSpan span;
region.center.latitude = map.region.center.latitude;
region.center.longitude = map.region.center.longitude;
span.latitudeDelta=map.region.span.latitudeDelta /2.0002;
span.longitudeDelta=map.region.span.longitudeDelta /2.0002;
region.span=span;
[map setRegion:region animated:TRUE];
}
-(IBAction)btnMinusClick:(id)sender
{
MKCoordinateRegion region;
MKCoordinateSpan span;
region.center.latitude = map.region.center.latitude;
region.center.longitude = map.region.center.longitude;
span.latitudeDelta=map.region.span.latitudeDelta *2.0002;
span.longitudeDelta=map.region.span.longitudeDelta *2.0002;
region.span=span;
[map setRegion:region animated:TRUE];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end