2015-02-24 100 views
0

我想注释添加到MKMapView添加自定义注释到的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 

我加入内部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; 
} 

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

+1

该代码有几个问题,但一个很大的问题是,在viewForAnnotation中,CustomMapAnnotationView从来没有真正的alloc + inited(dequeueReusableAnnotationViewWithIdentifier没有这样做)。如果viewForAnnotation甚至被调用,它必须返回nil,这意味着地图视图必须放置一个红色的针_somewhere_。记录添加注释的坐标并在那里查看。 – Anna 2015-02-24 19:55:39

+0

工作。如果它是nil,我添加了另一行来初始化annotationView。 – 2015-02-24 20:38:13

+0

该代码还有哪些其他问题? – 2015-02-24 20:39:27

回答

5

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

其他一些问题与代码:

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

那很完美。谢谢 – 2015-02-25 00:46:42