Jac*_*y.S 4 objective-c mkmapview mkannotation ios
我正在尝试为我的 Apple 地图上彼此非常接近的注释创建集群视图。我知道 Apple 在 iOS 11 中推出了原生集群视图套件,但我在网上找到的所有教程都是用 Swift 编写的。我希望有人可以教我或推荐我任何我可以阅读的教程,以了解如何在 Objective-C 中实现集群注释。
我的想法是创建一个ClusterView类,它继承MKAnnotationView类,然后在mapView控制器中创建ClusterView的实例。
我已经阅读了苹果的文档,它只为您提供了我可能需要调用的函数,但没有解释如何使用它们,这是苹果文档的链接: https: //developer.apple.com/文档/mapkit/mkclusterannotation?language=objc
任何帮助,将不胜感激!
以下是基本步骤:
\n\n定义注释视图,指定clusteringIdentifier和collisionMode:
// CustomAnnotationView.h\n\n@import MapKit;\n\n@interface CustomAnnotationView : MKMarkerAnnotationView\n\n@end\nRun Code Online (Sandbox Code Playgroud)\n\n和
\n\n// CustomAnnotationView.m\n\n#import "CustomAnnotationView.h"\n\nstatic NSString *identifier = @"com.domain.clusteringIdentifier";\n\n@implementation CustomAnnotationView\n\n- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {\n if ((self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier])) {\n self.clusteringIdentifier = identifier;\n self.collisionMode = MKAnnotationViewCollisionModeCircle;\n }\n\n return self;\n}\n\n- (void)setAnnotation:(id<MKAnnotation>)annotation {\n [super setAnnotation:annotation];\n\n self.clusteringIdentifier = identifier;\n}\n\n@end\nRun Code Online (Sandbox Code Playgroud)或者,如果需要,您可以定义自己的集群注释视图,指定displayPriority和collisionMode。这还更新了集群的图像以指示有多少注释被集群:
// ClusterAnnotationView.h\n\n@import MapKit;\n\n@interface ClusterAnnotationView : MKAnnotationView\n\n@end\nRun Code Online (Sandbox Code Playgroud)\n\n和
\n\n// ClusterAnnotationView.m\n\n#import "ClusterAnnotationView.h"\n\n@implementation ClusterAnnotationView\n\n- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {\n if ((self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier])) {\n self.displayPriority = MKFeatureDisplayPriorityDefaultHigh;\n self.collisionMode = MKAnnotationViewCollisionModeCircle;\n }\n\n return self;\n}\n\n- (void)setAnnotation:(id<MKAnnotation>)annotation {\n super.annotation = annotation;\n [self updateImage:annotation];\n}\n\n- (void)updateImage:(MKClusterAnnotation *)cluster {\n if (!cluster) {\n self.image = nil;\n return;\n }\n\n CGRect rect = CGRectMake(0, 0, 40, 40);\n UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rect.size];\n self.image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {\n // circle\n\n [[UIColor blueColor] setFill];\n [[UIColor whiteColor] setStroke];\n\n UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];\n path.lineWidth = 0.5;\n [path fill];\n [path stroke];\n\n // count\n\n NSString *text = [NSString stringWithFormat:@"%ld", (long) cluster.memberAnnotations.count];\n NSDictionary<NSAttributedStringKey, id> *attributes = @{\n NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleBody],\n NSForegroundColorAttributeName: [UIColor whiteColor]\n };\n CGSize size = [text sizeWithAttributes:attributes];\n CGRect textRect = CGRectMake(rect.origin.x + (rect.size.width - size.width) / 2,\n rect.origin.y + (rect.size.height - size.height) / 2,\n size.width,\n size.height);\n [text drawInRect:textRect withAttributes:attributes];\n }];\n}\n\n@end\nRun Code Online (Sandbox Code Playgroud)\n\n如果您不想,则不必为集群创建自己的子类。但这只是说明了如何完全控制集群的外观(如果您选择这样做)。
然后你的视图控制器只需要注册适当的类,你\xe2\x80\x99就完成了(不需要地图视图委托):
\n\n[self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];\nRun Code Online (Sandbox Code Playgroud)\n\n如果您想使用自定义集群视图,您也可以注册它:
\n\n[self.mapView registerClass:[ClusterAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultClusterAnnotationViewReuseIdentifier];\nRun Code Online (Sandbox Code Playgroud)\n\n例如:
\n\n// ViewController.m\n\n#import \xe2\x80\x9cViewController.h"\n\n@import MapKit;\n\n#import "CustomAnnotationView.h"\n#import "ClusterAnnotationView.h"\n\n@interface ViewController ()\n@property (weak, nonatomic) IBOutlet MKMapView *mapView;\n@end\n\n@implementation ViewController\n\n- (void)viewDidLoad {\n [super viewDidLoad];\n\n [self configureMapView];\n}\n\n- (void)configureMapView {\n self.mapView.userTrackingMode = MKUserTrackingModeFollow;\n\n [self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];\n [self.mapView registerClass:[ClusterAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultClusterAnnotationViewReuseIdentifier];\n}\n\n// I\xe2\x80\x99m going to search for restaurants and add annotations for those,\n// but do whatever you want\n\n- (void)performSearch {\n MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];\n request.naturalLanguageQuery = @"restaurant";\n request.region = self.mapView.region;\n\n MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];\n [search startWithCompletionHandler:^(MKLocalSearchResponse * _Nullable response, NSError * _Nullable error) {\n if (error) {\n NSLog(@"%@", error);\n return;\n }\n\n for (MKMapItem *mapItem in response.mapItems) {\n MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];\n annotation.coordinate = mapItem.placemark.coordinate;\n annotation.title = mapItem.name;\n annotation.subtitle = mapItem.placemark.thoroughfare;\n [self.mapView addAnnotation:annotation];\n }\n }];\n}\n\n@end\nRun Code Online (Sandbox Code Playgroud)得出:
\n\n\n