gpt4 book ai didi

ios - 如何在 Objective-C 中实现 MKClusterAnnotations?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:10:25 26 4
gpt4 key购买 nike

我正在尝试为我的 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

如有任何帮助,我们将不胜感激!

最佳答案

基本步骤如下:

  1. 定义注释 View ,指定 clusteringIdentifiercollisionMode:

    //  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
  2. 可选地,如果需要,您可以定义自己的集群注释 View ,指定 displayPrioritycollisionMode。这也更新集群的图像以指示有多少注释被集群:

    //  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

    如果你不想的话,你不必为集群创建自己的子类。但这只是说明了如果您选择这样做,您可以如何完全控制集群的外观。

  3. 然后您的 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

产生:

demo

关于ios - 如何在 Objective-C 中实现 MKClusterAnnotations?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54485635/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com