Search code examples
iosswiftmkmapviewcllocationmanagermkoverlay

How to stick an overlay to user location with MapKit in Swift


I created a mapView which find user's location and draws a green circle overlay around the user but I could not make a way to stick this green circle to user wether user is moving or stationary. All of my tries led to either make a tail of these circles after user or just one circle from user's first location.

In my viewDidLoad() I also initiated an instance of location manager which is where I get my location data from.

You can see my location manager delegate below.

my didUpdateLocations is:

//CLLocationManager Delegate
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    //create array of locations of user
    var locationArray = locations as NSArray
    //find the last object of location
    var locationObj = locationArray.lastObject as CLLocation
    //creating circle
    var newCircle = MKCircle(centerCoordinate: locationObj.coordinate, radius: 100 as CLLocationDistance)
    if locations.count>1 {
        //I tried dispatch but still tail of green circles
        dispatch_sync(dispatch_queue_t(), { () -> Void in
        self.treesMap.removeOverlay(newCircle)
        })
    }

     self.treesMap.addOverlay(newCircle)        
    //if location determination is fixed
    if  locationFixAchieved == false {
    //declare that location is fixed locationManager.location.coordinate
        locationFixAchieved = true

        var prevLocation = centreLocation
        self.centreLocationCoordinate = (locationObj.coordinate as CLLocationCoordinate2D)
            println("location changed")

        //for output purpose
        println("locations = \(locations)")                

     }

}

my renderForOverlay function is:

/circle overlay function
func mapView(
    mapView: MKMapView!, rendererForOverlay   overlay: MKOverlay!) -> MKOverlayRenderer! {
        //if the overlay was type of circle
        if (overlay.isKindOfClass(MKCircle))
        {
            //declaring circleRenderer variable
            var circleRenderer = MKCircleRenderer(overlay: overlay)
            //setting stroke color of the circle
            circleRenderer.strokeColor = UIColor.greenColor()
            //setting fill color of cirlce
            circleRenderer.fillColor = UIColor(
                red: 0,
                green: 1.0,
                blue: 0,
                alpha: 0.5)
            //return rendererForOverlay function
            return circleRenderer
        }
        //if overlay was not type of MKCircle
        return nil
}

I'm looking for a way that I can make the circle overlay stick to the users location all the time and move by it.


Solution

  • In this section of code:

    var newCircle = MKCircle(centerCoordinate: locationObj.coordinate, radius: 100 as CLLocationDistance)
    if locations.count>1 {
        //I tried dispatch but still tail of green circles
        dispatch_sync(dispatch_queue_t(), { () -> Void in
        self.treesMap.removeOverlay(newCircle)
        })
    }
    
    self.treesMap.addOverlay(newCircle)
    

    the removeOverlay line (if it even executes) does not remove the previous circle overlay.

    Instead, it tries to remove some new instance of a circle overlay (newCircle) which hasn't even been added to the map -- the line will essentially do nothing.


    Since the only overlay you want on the map is the single circle, before adding the new one, you can just call removeOverlays (plural) and tell the map to remove all existing overlays.

    Example:

    var newCircle = MKCircle(centerCoordinate: locationObj.coordinate, radius: 100 as CLLocationDistance)
    
    /* comment this block out -- don't need it
    if locations.count>1 {
        //I tried dispatch but still tail of green circles
        dispatch_sync(dispatch_queue_t(), { () -> Void in
        self.treesMap.removeOverlay(newCircle)
        })
    }
    */
    
    self.treesMap.removeOverlays(self.treesMap.overlays)
    
    self.treesMap.addOverlay(newCircle)