Iv been searching all around for a good explanation of how to make an MKCircle annotation for the MapView using Swift 2.0 but I cant seem to find an adequate explanation. Can someone post some example code showing how to create the MKCircle annotation? Here is the code i'm using to make the map and get the coordinate.
let address = self.location
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error)
}
if let placemark = placemarks?.first {
let coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
self.locationCoordinates = coordinates
let span = MKCoordinateSpanMake(0.005, 0.005)
let region = MKCoordinateRegion(center: self.locationCoordinates, span: span)
self.CIMap.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = self.locationCoordinates
self.CIMap.addAnnotation(annotation)
self.CIMap.layer.cornerRadius = 10.0
self.CIMap.addOverlay(MKCircle(centerCoordinate: self.locationCoordinates, radius: 1000))
}
})
Will show step wise approach about how to create a circular overlay on map view using swift 3 with xcode 8.3.3
In your main storyboard file drag map kit view on to the scene(view) of storyboard and create outlet for the same, here i created mapView. Also you want to create overlay dynamically whenever you go for long press on map, so drag Long Press Gesture Recognizer on to the mapView from object libary and then create action method for the same, here i had created addRegion() for the same.
create a global constant for CLLocationManager class so that it can be accessed in every function. And in your viewDidLoad method, add some code for getting authorization from the user.
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
Add code for generating a circular region whenever you do long press gesture recognizer in your long press gesture recognizer action method addRegion().
@IBAction func addRegion(_ sender: Any) {
print("addregion pressed")
guard let longPress = sender as? UILongPressGestureRecognizer else {return}
let touchLocation = longPress.location(in: mapView)
let coordinates = mapView.convert(touchLocation, toCoordinateFrom: mapView)
let region = CLCircularRegion(center: coordinates, radius: 5000, identifier: "geofence")
mapView.removeOverlays(mapView.overlays)
locationManager.startMonitoring(for: region)
let circle = MKCircle(center: coordinates, radius: region.radius)
mapView.add(circle)
}
Still you won't see circle physically on the map until you render circle on map. for this you need to implement delegate of mapviewdelegate.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {}
To make code look more cleaner you can create extension after last brace where your class ends. One extension contains code for CLLocationManagerDelegate and other for MKMapViewDelegate.
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
mapView.showsUserLocation = true
}
}
you should call locationManager.stopUpdatingLocation() in delegate method so that your battery does not drain out.
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let circelOverLay = overlay as? MKCircle else {return MKOverlayRenderer()}
let circleRenderer = MKCircleRenderer(circle: circelOverLay)
circleRenderer.strokeColor = .blue
circleRenderer.fillColor = .blue
circleRenderer.alpha = 0.2
return circleRenderer
}
}
Here we are making the actual circle on the screen.
Final code should look like this.
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
// MARK: Long Press Gesture Recognizer Action Method
@IBAction func addRegion(_ sender: Any) {
print("addregion pressed")
guard let longPress = sender as? UILongPressGestureRecognizer else {return}
let touchLocation = longPress.location(in: mapView)
let coordinates = mapView.convert(touchLocation, toCoordinateFrom: mapView)
let region = CLCircularRegion(center: coordinates, radius: 5000, identifier: "geofence")
mapView.removeOverlays(mapView.overlays)
locationManager.startMonitoring(for: region)
let circle = MKCircle(center: coordinates, radius: region.radius)
mapView.add(circle)
}
}
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
mapView.showsUserLocation = true
}
}
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let circelOverLay = overlay as? MKCircle else {return MKOverlayRenderer()}
let circleRenderer = MKCircleRenderer(circle: circelOverLay)
circleRenderer.strokeColor = .blue
circleRenderer.fillColor = .blue
circleRenderer.alpha = 0.2
return circleRenderer
}
}
First you need to add MKMapViewDelegate to the class defenition.
mapView.delegate = self
Set the maps delegate to self in your viewDidLoad.
Setting the annotation
mapView.addOverlay(MKCircle(centerCoordinate: CLLocationCoordinate2D, radius: CLLocationDistance))
mapView rendererForOverlay should now be called in the mapViews delegate and there you get to draw it
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKCircle {
let circleRenderer = MKCircleRenderer(circle: overlay)
circleRenderer.fillColor = UIColor.blueColor()
return circleRenderer
}
}
Also, you need to import MapKit for it all to compile
An overlay is merely a set of numbers. The thing that is visible in the map view is an overlay renderer. You must implement mapView:rendererForOverlay:
to supply the overlay renderer; otherwise, you will see nothing.