user1269290
user1269290

Reputation: 481

Detecting MapView finished changing region

I have a MKMapView that has annotations. My goal is to hide the annotation, if one is selected, when the map finished scrolling.

When an annotation is called I assign the annotation into a variable to keep track of it.

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    lastSelectedAnnotation = view.annotation
}

I know of:

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool){ }

However, I cannot figure out (beginner here), how to detect that the map finished changing its region so I can call my function:

func hideSelectedAnnotation(_ mapView: MKMapView) {
    DispatchQueue.main.async {
        mapView.deselectAnnotation(self.lastSelectedAnnotation, animated: true)
        self.lastSelectedAnnotation = nil
    }
}

I hide the annotation also when an accessory button is tapped:

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl){
    hideSelectedAnnotation(mapView)}

I have tried saving the coordinate of the region, and comparing them to the map but the map does not neccessarily center the annotation. I could also start a timer and when regionDidChangeAnimated is no longer called hide the annotation. But that seams like butchering it.

Thanks for any help!

Upvotes: 1

Views: 1679

Answers (1)

Sanzio Angeli
Sanzio Angeli

Reputation: 3922

I think you already figured it out...

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool){
    // Call your function here
}

Should fire every time the map view region changes (unless the change was inflicted by the user's finger)

----- EDIT -----

Unfortunately, you have to detect user input using a UIPanGestureRecognizer.

I have used, with success, A UIPanGestureRecognizer like the following:

lazy var mapPanGestureRecognizer: UIPanGestureRecognizer = {
    let gr = UIPanGestureRecognizer(target: self, action: #selector(draggedMap))
    gr.delegate = self
    return gr
}()

You will also have to add the UIPanGestureRecognizer to the map with

yourMap.addGestureRecognizer(mapPanGestureRecognizer)

You can then manage what happens in the #selector function by checking the state of the gesture, like so

@objc func draggedMap(panGestureRecognizer: UIPanGestureRecognizer) {
    // Check to see the state of the passed panGestureRocognizer
    if panGestureRecognizer.state == UIGestureRecognizer.State.began {
        // Do something
    }
}

The state is what allows you to determine if the user ended a gesture, is in the middle of a gesture, or began a gesture. List of possible states

Upvotes: 1

Related Questions