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