Search code examples
iosmapkitmapkitannotation

Preventing annotation deselection in MKMapView


I have a situation in my app where I want to disable annotation deselection (other than when selecting another), so when I tap anywhere that is not an annotation view, it should leave the currently selected annotation as is. If I tap on another annotation view, it should select that one and deselect the other.

I was hoping to find something along the lines of a willDeselectAnnotationView in the MKMapViewDelegate or an isDeselected in MKAnnotationView, but there's unfortunately no such thing. I also tried overriding deselectAnnotation in a custom subclass of MKMapView, but it seems the tap triggered deselect doesn't invoke that function.

Is it possible to disable annotation deselection while preserving the ability to select? Thanks!


Solution

  • I've found a way to do it! Make a boolean named something like "allowSelectionChanges", which I just have as global for now. Then use a subclass of MKMapView with this overriden function inside:

    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
            return allowSelectionChanges
        } 
    

    Switch this variable to false whenever you want to prevent annotation selection and deselection. It won't affect the user's ability to move around the map!


    Here's an example of how this can be used to stop a callout from getting deselected when you tap on it to interact with it. Put this in your MKAnnotationView subclass:

    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
            let rect = self.bounds
            var isInside = CGRectContainsPoint(rect, point)
            if !isInside {
                for view in self.subviews {
                    isInside = CGRectContainsPoint(view.frame, point)
                    if isInside {
                        allowSelectionChanges = false
                        return true
                    }
                }
                allowSelectionChanges = true
            }
    
            return false
        }