CustomMapAnnotationView

CustomMapAnnotationView

我正在尝试将注释添加到MKMapView

我创建了一个符合CustomMapPin协议的类MKAnnotation

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface CustomMapPin : NSObject <MKAnnotation> {

    CLLocationCoordinate2D coordinate;
    NSString *title;
    NSString *subtitle;
}

@property(nonatomic, assign) CLLocationCoordinate2D coordinate;
@property(nonatomic, copy) NSString *title;
@property(nonatomic, copy) NSString *subtitle;
@property(nonatomic, strong) NSString *type; // this is to differentiate between the different annotations on the map

@end


我创建了一个类CustomMapAnnotationView,它是MKAnnotationView的子类。

CustomMapAnnotationView.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface CustomMapAnnotationView : MKAnnotationView
@property (nonatomic, strong) UIImageView *annotationImage;
@end


CustomMapAnnotationView.m

#import "CustomMapAnnotationView.h"

@implementation CustomMapAnnotationView

-(id) initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];

    if (self) {
        self.frame = CGRectMake(0, 0, 28, 40);
        self.backgroundColor = [UIColor clearColor];

        self.annotationImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 28, 40)];
        self.annotationImage.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:self.annotationImage];

    }
    return self;
}

@end


我在FindMechanicViewControllerCLLocationManagerDelegateMKMapViewDelegate中添加自定义引脚

该代码段是:

-(void) viewWillAppear:(BOOL)animated {
    [self.locationManager startUpdatingLocation];
    self.currentLocation = [self.locationManager location];

    // Set the region of the map
    MKCoordinateSpan mapViewSpan = MKCoordinateSpanMake(0.01, 0.01);
    MKCoordinateRegion mapRegion = MKCoordinateRegionMake(self.currentLocation.coordinate, mapViewSpan);
    [self.mapView setRegion:mapRegion];

    // Add custom pin showing user location
    CustomMapPin *annotation = [[CustomMapPin alloc] init];
    annotation.title = @"Current Location";
    annotation.coordinate = self.currentLocation.coordinate;
    annotation.type = @"user location";
    [self.mapView addAnnotation:annotation];
}


和委托方法

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    static NSString *reuseId = @"CustomMapPin";
    CustomMapAnnotationView *annotationView = (CustomMapAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];

    if ([annotation isKindOfClass:[CustomMapPin class]]) {
        CustomMapPin *customAnnotation = (CustomMapPin *)annotation;

       if ([customAnnotation.type isEqualToString:@"user location"]) {
           [annotationView setAnnotation:customAnnotation];
           [annotationView setImage:[UIImage imageNamed:@"pin_user"]];
           [annotationView setCanShowCallout:YES];
        }

    }
    return annotationView;
}


这不会在地图上显示任何内容。我该如何解决 ?

最佳答案

viewForAnnotation中,CustomMapAnnotationView实际上从未分配+初始化(dequeueReusableAnnotationViewWithIdentifier不会这样做)。

如果viewForAnnotation甚至被调用,它必须返回nil,这意味着地图视图必须在某个地方放置红色大头针(如果未调用委托方法,则地图视图将再次默认为红色销)。记录要在其中添加注释的坐标,然后在此处查看。

更正后的viewForAnnotation可能看起来像这样:

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[CustomMapPin class]]) {
        static NSString *reuseId = @"CustomMapPin";

        CustomMapAnnotationView *annotationView = (CustomMapAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
        if (!annotationView) {
            annotationView = [[CustomMapAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
            [annotationView setCanShowCallout:YES];
        }

        CustomMapPin *customAnnotation = (CustomMapPin *)annotation;

        //view's annotation should be set regardless of "type"
        [annotationView setAnnotation:customAnnotation];

        if ([customAnnotation.type isEqualToString:@"user location"]) {
            [annotationView setImage:[UIImage imageNamed:@"pin_user"]];
        }
        else {
            //If it's not a "user location", then set image
            //to something else otherwise image will either be nil
            //or it will show some other annotation's image...
            [annotationView setImage:[UIImage imageNamed:@"pin_other"]];
        }

        return annotationView;
    }

    return nil;
}


代码的其他一些问题:


viewWillAppear中,代码在调用startUpdatingLocation后立即检索位置。不能保证每次都能正常工作,即使它“正常”工作,您很可能也会获得旧的缓存位置。如果它不起作用,则注释将以0,0(大西洋)结尾,否则应用将因坐标无效而崩溃。最好在didUpdateLocations委托方法中读取位置。在viewWillAppear中,先呼叫startUpdatingLocation,然后在didUpdateLocations中,如果位置的准确性和年龄适合您,请呼叫stopUpdatingLocation,然后使用该位置(创建并添加注释等)。
CustomMapAnnotationView中,创建并添加了annotationImage对象,但从未设置其image属性。实际上,annotationImage从未真正用于任何用途。
整个CustomMapAnnotationView类对于您的目的都是不必要的。在viewForAnnotation中,代码正在image上设置CustomMapAnnotationView属性(而不是使用annotationImage)。此image属性是从MKAnnotationView继承的。内置的基本MKAnnotationView类是您执行工作所需的全部。它已经具有image属性,并会自动为您显示它(您无需创建自己的UIImageView)。

10-08 05:55