Currently I am trying to use the new clustering feature introduced in iOS 11. However I am finding that when I use the clustering feature, I lose the functionality of my initial annotations including the callout and what happens when the annotation is clicked. I believe it is because the I create the cluster in a different class than my annotations. It seems as though with my current code I can have only one or the other. Customized pins that don't cluster when you zoom out, or clustering pins with lost information. Does anyone know of a better way to do this? Below I have attached code showing how I create the pin callouts and how I create clustering. Is there a way in which I can have both features?
Creating Callouts
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if #available(iOS 11.0, *) {
// 2
guard let annotation = annotation as? CalloutPin else { return nil }
// 3
let identifier = "Pin"
var view: MKMarkerAnnotationView
// 4
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
as? MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
// 5
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
return view
}
else{
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin-annotation")
annotationView.animatesDrop = true
annotationView.canShowCallout = true
return nil
}
}
Code to create clustering
@available(iOS 11.0, *)
class PinView :MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
//if let pin = newValue as? Pin {
clusteringIdentifier = "pin"
displayPriority = .defaultHigh
//}
}
}
}
@available(iOS 11.0, *)
class ClusterView: MKAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
displayPriority = .defaultHigh
collisionMode = .circle
centerOffset = CGPoint(x: 0, y: -10) // Offset center point to animate better with marker annotations
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var annotation: MKAnnotation? {
willSet {
if let cluster = newValue as? MKClusterAnnotation {
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 40, height: 40))
let count = cluster.memberAnnotations.count
image = renderer.image { _ in
// Fill full circle with tricycle color
UIColor.red.setFill()
UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 40, height: 40)).fill()
// Finally draw count text vertically and horizontally centered
let attributes = [ NSAttributedStringKey.foregroundColor: UIColor.white,
NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 20)]
let text = "\(count)"
let size = text.size(withAttributes: attributes)
let rect = CGRect(x: 20 - size.width / 2, y: 20 - size.height / 2, width: size.width, height: size.height)
text.draw(in: rect, withAttributes: attributes)
}
}
}
}