4

I'm trying to work with the new features added to the mapview in ios11.

I'm clustering all my MKAnnotationView with circle collision but I have to check in real time when the annotation becomes clustered.

I have no idea how to do that.

EDIT (4/1/2018) :

More informations : When I select an annotation I add a custom CallOutView when the didSelect method is called and remove the CallOut when the didDeselect method is called.

The issue is when an annotation is selected and becomes clustered, when you zoom in the annotation is still selected but in "normal" state.

I want to remove the CallOut of my selected annotation when it become clustered like the didDeselect method.

Below screenshot to illustrate my issue :

1 - Annotation Selected

2 - Annotation Clustered

3 - Annotation Zoom In after cluster

I think it's just an issue of comprehension.

Any help would be really appreciated. Thank you in advance

3 Answers3

4

In iOS 11, Apple also introduce a new callback in MKMapViewDelegate:

func mapView(_ mapView: MKMapView, clusterAnnotationForMemberAnnotations memberAnnotations: [MKAnnotation]) -> MKClusterAnnotation

Before annotations become clustered, this function will be called to request a MKClusterAnnotation for memberAnnotations. So the second parameter named memberAnnotations indicates the annotations to be clustered.

EDIT (4/1/2018):

There are two key steps for cluster annotation:

First, before annotations become clustered, MapKit invoke mapView:clusterAnnotationForMemberAnnotations: function to request a MKClusterAnnotation for memberAnnotations.

Secondly, MapKit add the MKClusterAnnotation to MKMapView, and mapView:viewForAnnotation: function will be called to produce a MKAnnotationView.

So you can deselect annotation in either of the two steps, like this:

var selectedAnnotation: MKAnnotation? //the selected annotation

 func mapView(_ mapView: MKMapView, clusterAnnotationForMemberAnnotations memberAnnotations: [MKAnnotation]) -> MKClusterAnnotation {
     for annotation in memberAnnotations {
         if annotation === selectedAnnotation {
             mapView.deselectAnnotation(selectedAnnotation, animated: false)//Or remove the callout
         }
     }

     //...
 }

Or:

 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
     if let clusterAnnotation = annotation as? MKClusterAnnotation {
         for annotation in clusterAnnotation.memberAnnotations {
             if annotation === selectedAnnotation {
                 mapView.deselectAnnotation(selectedAnnotation, animated: false)//Or remove the callout
             }
         }
     }

     //...
 }
devliubo
  • 161
  • 4
  • Thank you, I didn't know. I'm just stuck on how to get only the selected annotation. I want to deselect the selected annotation when clustered (only this one) – Seiki Kisekash Jan 04 '18 at 12:24
  • @SeikiKisekash , I update my answer for your problem. – devliubo Jan 05 '18 at 04:07
  • Thank's a lot for your answer ! I used : func mapView(_ mapView: MKMapView, clusterAnnotationForMemberAnnotations memberAnnotations: [MKAnnotation]) -> MKClusterAnnotation Now, I encounter a new problem and can't continue to work on my app. My app crash when I zoom in / zoom out the annotation. I tried a solve with this : https://forums.developer.apple.com/thread/89427 And my issue is the same as : https://openradar.appspot.com/36131654 For sure, the issue is not related to the deselect but I'm still stuck. – Seiki Kisekash Jan 18 '18 at 06:44
3

When a new cluster is formed, mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? will be called to request for a new view for that cluster.

You can do you check like this:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    //...
    if annotation is MKClusterAnnotation {
        //This is your new cluster.
    }
    //Alternatively if you need to use the values within that annotation you can do
    if let cluster = annotation as? MKClusterAnnotation {

    }
    //...
}
Ben Ong
  • 913
  • 1
  • 10
  • 25
  • Thank you for your explaination, it is really helpfull for the solving of my issue. I'm still stuck, I just added more informations about my issue I will continue to work on this to solve. – Seiki Kisekash Jan 04 '18 at 12:22
2

I'm two years late to the party here, but just wanted to say you could also detect if a cluster was selected vs. an individual annotation by:

        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {

            // selected annotation belongs to a cluster
            if view.annotation is MKClusterAnnotation {
                print("selected a cluster")
            }
        }
Kyle Beard
  • 604
  • 5
  • 18