向MKMapview添加自定义注释 [英] Adding a custom annotation to a MKMapview

查看:104
本文介绍了向MKMapview添加自定义注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to add annotations to a MKMapView

我创建了一个符合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的子类

I have created a class CustomMapAnnotationView which is a subclass of 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

我要在FindMechanicViewControllerMKMapViewDelegate

代码段是:

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

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

This does not show anything on the map. How do I fix this ?

推荐答案

viewForAnnotation中,CustomMapAnnotationView从未实际分配+初始化(dequeueReusableAnnotationViewWithIdentifier不会执行此操作).

In viewForAnnotation, CustomMapAnnotationView is never actually alloc+inited (the dequeueReusableAnnotationViewWithIdentifier does not do this).

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

If viewForAnnotation is even getting called, it must be returning nil which means the map view must be putting a red pin somewhere (and if the delegate method isn't getting called, then again the map view will default to a red pin). Log the coordinates where the annotation is being added and look there.

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

A corrected viewForAnnotation might look like this:

-(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中,代码在CustomMapAnnotationView上设置了image属性(而不是使用annotationImage).此image属性是从MKAnnotationView继承的.内置的基本MKAnnotationView类是您执行工作所需的全部.它已经具有image属性,它会自动为您显示该属性(您无需创建自己的UIImageView).
  1. In viewWillAppear, code is retrieving the location immediately after calling startUpdatingLocation. This is not guaranteed to work every time and even if it does "work", you will most likely be getting an old, cached location. When it doesn't work, the annotation will either end up at 0,0 (Atlantic Ocean) or app will crash due to invalid coordinates. It's much better to read the location in the didUpdateLocations delegate method. In viewWillAppear, call startUpdatingLocation and then in didUpdateLocations, if the accuracy and age of the location is adequate for you, call stopUpdatingLocation and then use the location (create and add the annotation, etc).
  2. In CustomMapAnnotationView, annotationImage object is created and added but its image property is never set. The annotationImage is actually never really used for anything.
  3. The whole CustomMapAnnotationView class is unnecessary for your purpose . In viewForAnnotation, code is setting the image property on the CustomMapAnnotationView (instead of using annotationImage). This image property is inherited from MKAnnotationView. The built-in, basic MKAnnotationView class is all you need for what you're doing. It already has an image property and it automatically displays it for you (you don't need to create your own UIImageView).

这篇关于向MKMapview添加自定义注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆