MKClusterAnnotation

Hey there,


i know there have been lot of questions about this topic but as i am pretty new to programming i just could never find the right solution.


I am trying to display several custom annotations on a map and it lags a lot, so after researching for while, i found out, that the best solution is to cluster my annotations.

I read a lot about this topic but i could never actually find a proper explanation/ tutorial, how to implement it into my code.


My code looks like this:

import UIKit
import MapKit

struct Location {
    let title: String
    let latitude: Double
    let longitude: Double
}
/////////////////////////
let locations = [
    Location(title: "Pin1", latitude: 20.147973, longitude: 100.617178),
    Location(title: "Pin2", latitude: 20.145801, longitude: 100.616343)
    //i left out most of the annotations to minimize the space taken away
]
/////////////////////////

class customAnnotation: MKPointAnnotation {
    var isCollapsed = true
    var setNeedsToggle = false
}

class ViewController: UIViewController, MKMapViewDelegate {
    
    @IBOutlet weak var mapView: MKMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        for location in locations {
            let annotation = customAnnotation()
            annotation.title = location.title
            annotation.coordinate = CLLocationCoordinate2D (latitude: location.latitude, longitude: location.longitude)
            mapView.addAnnotation(annotation)
        }
        self.mapView.delegate = self
    }
    
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard let annot = annotation as? customAnnotation else { return nil }
        
        if annotation is MKUserLocation {
            return nil
        }
        let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customAnnotation")
        annotationView.image = UIImage(named: "pin")
        annotationView.canShowCallout = true
        
        let rightButton = UIButton(type: .detailDisclosure)
        rightButton.setImage(UIImage(named: annot.isCollapsed ? "ic_showmore" : "ic_showless"), for: .normal)
        annotationView.rightCalloutAccessoryView = rightButton
        
        if (annot.isCollapsed) {
            annotationView.detailCalloutAccessoryView = nil
        }
        else {
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
            label.text = "Description Shown When Button is Tapped"
            label.font = UIFont.italicSystemFont(ofSize: 14.0)
            label.numberOfLines = 0
            annotationView.detailCalloutAccessoryView = label
            
            label.widthAnchor.constraint(lessThanOrEqualToConstant: label.frame.width).isActive = true
            label.heightAnchor.constraint(lessThanOrEqualToConstant: 90.0).isActive = true
        }
        return annotationView
    }
    
    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        guard let oldAnnot = view.annotation as? customAnnotation else { return }
        
        let annotation = customAnnotation()
        annotation.title = oldAnnot.title
        annotation.coordinate = oldAnnot.coordinate
        annotation.setNeedsToggle = true
        
        if (oldAnnot.isCollapsed) {
            annotation.isCollapsed = false
        }
       
        mapView.removeAnnotation(oldAnnot)
        mapView.addAnnotation(annotation)
    }
    
    internal func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
        for view in views {
            if let annotation = view.annotation as? customAnnotation, annotation.setNeedsToggle {
                mapView.selectAnnotation(annotation, animated: true)
                return
            }
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}



maybe you have an idea how to iclude annotation clustering in a few simple steps or you can link a proper tutorial about how to do this.


Thanks a lot,

Gus

Replies

Have you seen our sample code project for clustering annotations?

I have

i just had a problem converting it into my code as in Tandm everything is split up into many different swift files


what i just found was the following solution:

in the mapView-function developing the annotationView all i had to do was:

let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customAnnotation")  
annotationView.clusteringIdentifier = "annotCluster"
annotationView.image = UIImage(named: "pin")  
annotationView.canShowCallout = true 


so its fine now