A drop-in MKAnnotation clustering library for iOS.
Update February 1, 2015
Kingpin is now 0.2.
If you are coming from 0.1, be sure to review README for changes.
- Uses a 2-d tree under the hood for maximum performance.
- No subclassing required, making the library easy to integrate with existing projects.
Install via CocoaPods. To get stable release in your Podfile
add:
pod 'kingpin'
then run
pod install
If you want to use the latest version from kingpin's master, point your Podfile to the git:
pod 'kingpin', :git => 'https://github.com/itsbonczek/kingpin'
Create an instance of KPClusteringController
. You'll likely want to do this inside a view controller containing a map view.
self.clusteringController = [[KPClusteringController alloc] initWithMapView:self.mapView]
Set the controller's annotations:
[self.clusteringController setAnnotations:[self annotations]];
Handle the clusters:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *annotationView = nil;
if ([annotation isKindOfClass:[KPAnnotation class]]) {
KPAnnotation *kingpinAnnotation = (KPAnnotation *)annotation;
if ([kingpinAnnotation isCluster]) {
annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"cluster"];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:kingpinAnnotation reuseIdentifier:@"cluster"];
}
annotationView.pinColor = MKPinAnnotationColorPurple;
} else {
annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pin"];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:[kingpinAnnotation.annotations anyObject] reuseIdentifier:@"pin"];
}
annotationView.pinColor = MKPinAnnotationColorRed;
}
annotationView.canShowCallout = YES;
}
return annotationView;
}
Customize the annotations:
- (void)clusteringController:(KPClusteringController *)clusteringController configureAnnotationForDisplay:(KPAnnotation *)annotation {
annotation.title = [NSString stringWithFormat:@"%lu custom annotations", (unsigned long)annotation.annotations.count];
annotation.subtitle = [NSString stringWithFormat:@"%.0f meters", annotation.radius];
}
Also, see example on how to use kingpin with your own custom annotations in Wiki/Examples.
Note: You can gain access to the cluster's annotations via -[KPAnnotation annotations]
.
Refresh visible annotations as needed:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
[self.clusteringController refresh:self.animationSwitch.on];
}
This is typically done in -mapView:regionDidChangeAnimated:
To configure the clustering algorithm, create an instance of KPGridClusteringAlgorithm and use it to instantiate a KPClusteringController:
KPGridClusteringAlgorithm *algoritm = [KPGridClusteringAlgorithm new];
algorithm.gridSize = CGSizeMake(50, 50); // cluster grid cell size
algorithm.annotationSize = CGSizeMake(25, 50); // annotation view size
algorithm.clusteringStrategy = KPGridClusteringAlgorithmStrategyTwoPhase;
KPClusteringController *clusteringController = [[KPClusteringController alloc] initWithMapView:self.mapView clusteringAlgorithm:algorithm];
Kingpin uses simple grid-based clustering algorithm backed by k-d tree.
The good demonstration of this algorithm can be found in WWDC Session 2011: "Visualizing Information Geographically with MapKit".
Kingpin's algorithm works in two steps (phases):
- The first step produces a cluster grid by querying a 2-d tree.
- The second step merges clusters in this cluster grid that visually overlap.
See CHANGELOG for details. All versions are tagged accordingly.
Check out the tester target in kingpin.xcodeproj
Apache 2.0