- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试为我的 Apple map 上彼此非常接近的注释创建聚类 View 。我知道 Apple 在 iOS 11 中推出了原生集群 View 工具包,但我在网上找到的所有教程都是用 Swift 编写的。我希望有人可以教我或向我推荐任何我可以阅读的教程,以了解如何在 Objective-C 中实现集群注释。
我的想法是创建一个ClusterView类,它继承了MKAnnotationView类,然后在mapView Controller 中创建一个ClusterView的实例。
我看过apple的文档,它只提供了我可能需要调用的函数,但没有说明如何使用,这是Apple文档的链接:https://developer.apple.com/documentation/mapkit/mkclusterannotation?language=objc
如有任何帮助,我们将不胜感激!
最佳答案
基本步骤如下:
定义注释 View ,指定 clusteringIdentifier
和 collisionMode
:
// CustomAnnotationView.h
@import MapKit;
@interface CustomAnnotationView : MKMarkerAnnotationView
@end
和
// CustomAnnotationView.m
#import "CustomAnnotationView.h"
static NSString *identifier = @"com.domain.clusteringIdentifier";
@implementation CustomAnnotationView
- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier])) {
self.clusteringIdentifier = identifier;
self.collisionMode = MKAnnotationViewCollisionModeCircle;
}
return self;
}
- (void)setAnnotation:(id<MKAnnotation>)annotation {
[super setAnnotation:annotation];
self.clusteringIdentifier = identifier;
}
@end
可选地,如果需要,您可以定义自己的集群注释 View ,指定 displayPriority
和 collisionMode
。这也更新集群的图像以指示有多少注释被集群:
// ClusterAnnotationView.h
@import MapKit;
@interface ClusterAnnotationView : MKAnnotationView
@end
和
// ClusterAnnotationView.m
#import "ClusterAnnotationView.h"
@implementation ClusterAnnotationView
- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier])) {
self.displayPriority = MKFeatureDisplayPriorityDefaultHigh;
self.collisionMode = MKAnnotationViewCollisionModeCircle;
}
return self;
}
- (void)setAnnotation:(id<MKAnnotation>)annotation {
super.annotation = annotation;
[self updateImage:annotation];
}
- (void)updateImage:(MKClusterAnnotation *)cluster {
if (!cluster) {
self.image = nil;
return;
}
CGRect rect = CGRectMake(0, 0, 40, 40);
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rect.size];
self.image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
// circle
[[UIColor blueColor] setFill];
[[UIColor whiteColor] setStroke];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
path.lineWidth = 0.5;
[path fill];
[path stroke];
// count
NSString *text = [NSString stringWithFormat:@"%ld", (long) cluster.memberAnnotations.count];
NSDictionary<NSAttributedStringKey, id> *attributes = @{
NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleBody],
NSForegroundColorAttributeName: [UIColor whiteColor]
};
CGSize size = [text sizeWithAttributes:attributes];
CGRect textRect = CGRectMake(rect.origin.x + (rect.size.width - size.width) / 2,
rect.origin.y + (rect.size.height - size.height) / 2,
size.width,
size.height);
[text drawInRect:textRect withAttributes:attributes];
}];
}
@end
如果你不想的话,你不必为集群创建自己的子类。但这只是说明了如果您选择这样做,您可以如何完全控制集群的外观。
然后您的 View Controller 只需要注册适当的类就可以了(不需要 map View 委托(delegate)):
[self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];
如果你想使用你的自定义集群 View ,你也可以注册它:
[self.mapView registerClass:[ClusterAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultClusterAnnotationViewReuseIdentifier];
例如:
// ViewController.m
#import “ViewController.h"
@import MapKit;
#import "CustomAnnotationView.h"
#import "ClusterAnnotationView.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self configureMapView];
}
- (void)configureMapView {
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
[self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];
[self.mapView registerClass:[ClusterAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultClusterAnnotationViewReuseIdentifier];
}
// I’m going to search for restaurants and add annotations for those,
// but do whatever you want
- (void)performSearch {
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = @"restaurant";
request.region = self.mapView.region;
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", error);
return;
}
for (MKMapItem *mapItem in response.mapItems) {
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = mapItem.placemark.coordinate;
annotation.title = mapItem.name;
annotation.subtitle = mapItem.placemark.thoroughfare;
[self.mapView addAnnotation:annotation];
}
}];
}
@end
产生:
关于ios - 如何在 Objective-C 中实现 MKClusterAnnotations?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54485635/
在 iOS 11 中,默认行为是 map View 中的注释在缩小时聚集在一起。我不希望这种情况发生在我的用例中,因此我尝试禁用此默认行为。我尝试通过从可选的 MKMapViewDelegate 方法
我正在尝试为我的 Apple map 上彼此非常接近的注释创建聚类 View 。我知道 Apple 在 iOS 11 中推出了原生集群 View 工具包,但我在网上找到的所有教程都是用 Swift 编
我有一个实现 MKAnnotation 协议(protocol)的 MapItem 类。我正在使用 MKMarkerAnnotationView 在 map 上显示注释。 根据文档,MKMarkerA
我是一名优秀的程序员,十分优秀!