Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw a circle of 1000m radius around users location in MKMapView

(Using iOS 5 and Xcode 4.2)

I have an MKMapView and want to draw a circle of 1000m radius around the user location.

On the surface it would seem that implementing the mapView:viewForAnnotation: map view delegate method, and adding a custom MKAnnotationView for the users location, would be a perfect solution. It would look something like this:

- (MKAnnotationView *)mapView:(MKMapView *)mapView             viewForAnnotation:(id <MKAnnotation>)annotation {     // If it's the user location, return my custom MKAnnotationView.     if ([annotation isKindOfClass:[MKUserLocation class]]) {         return myCustomAnnotationView;     } else {         return nil;     } } 

However annotations on the map don't scale when you zoom in and out of the map.

So I tried adding an overlay (because overlays scale with the map), using the MKCircle class and setting its co-ordinates to the latest co-ordinates from my locationManger/map view delegate. However as the coordinate property of MKCircle is readonly, I'm having to remove the overlay then add a new one each time the user moves. Causing a noticeable flicker as it happens.

Is there any way to make an annotation scale seamlessly as the map view is scaled in and out? Or is there a good way to make an overlay move seamlessly with changes in the users location?

I would be very grateful for your help :)

like image 566
Jon Cox Avatar asked Jan 29 '12 20:01

Jon Cox


2 Answers

Try a custom overlay. Add this in viewDidLoad:

MKCircle *circle = [MKCircle circleWithCenterCoordinate:userLocation.coordinate radius:1000]; [map addOverlay:circle]; 

userLocation can be obtained by storing the MKUserLocationAnnotation as a property. Then, to actually draw the circle, put this in the map view's delegate:

- (MKOverlayRenderer *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay {     MKCircleRenderer *circleView = [[MKCircleRenderer alloc] initWithOverlay:overlay];     circleView.strokeColor = [UIColor redColor];     circleView.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.4];     return circleView; } 
like image 177
benwad Avatar answered Oct 07 '22 19:10

benwad


An updated version for iOS 8.0 using Swift.

import Foundation import MapKit  class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate{     var locationManager: CLLocationManager = CLLocationManager()      @IBOutlet var mapView: MKMapView!      override func viewDidLoad() {         super.viewDidLoad()          // We use a predefined location         var location = CLLocation(latitude: 46.7667 as CLLocationDegrees, longitude: 23.58 as CLLocationDegrees)          addRadiusCircle(location)     }      func addRadiusCircle(location: CLLocation){         self.mapView.delegate = self         var circle = MKCircle(centerCoordinate: location.coordinate, radius: 10000 as CLLocationDistance)         self.mapView.addOverlay(circle)     }      func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {         if overlay is MKCircle {             var circle = MKCircleRenderer(overlay: overlay)             circle.strokeColor = UIColor.redColor()             circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)             circle.lineWidth = 1             return circle         } else {             return nil         }     } } 
like image 38
vladCovaliov Avatar answered Oct 07 '22 18:10

vladCovaliov