将自定义注释添加到MKMapview

我正在尝试添加批注到MKMapView

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

 #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 

我创build了一个类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 

我在FindMechanicViewController里添加了一个自定义的引脚,它是一个CLLocationManagerDelegateMKMapViewDelegate

代码片段是:

 -(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; } 

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

viewForAnnotationCustomMapAnnotationView从来没有真正的alloc + inited( dequeueReusableAnnotationViewWithIdentifier不会这样做)。

如果viewForAnnotation甚至被调用,它必须返回nil ,这意味着地图视图必须在某处放置一个红色的针(如果委托方法没有被调用,那么地图视图将再次默认为红色的针)。 logging添加注释的坐标并在那里查看。

更正的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; } 

代码的其他一些问题:

  1. viewWillAppear ,代码在调用startUpdatingLocation后立即检索该位置。 这并不保证每次都能正常工作,即使它“工作”,也很可能会得到一个旧的,caching的位置。 当它不起作用时,注释将以0,0(大西洋)结束,否则应用程序将因无效坐标而崩溃。 读取didUpdateLocations委托方法中的位置会更好。 在viewWillAppear ,调用startUpdatingLocation ,然后在didUpdateLocations ,如果位置的准确性和年龄足够适用于您,请调用stopUpdatingLocation ,然后使用该位置(创build并添加注释等)。
  2. CustomMapAnnotationView ,创build并添加了annotationImage对象,但其image属性从未设置。 annotationImage实际上从来没有真正用于任何事情。
  3. 整个CustomMapAnnotationView类对于您的目的是不必要的。 在viewForAnnotation ,代码是在CustomMapAnnotationView (而不是使用annotationImage )上设置image属性。 这个image属性是从MKAnnotationViewinheritance的。 内置的,基本的MKAnnotationView类是你所需要做的。 它已经有一个image属性,它会自动显示给你(你不需要创build自己的UIImageView )。