MKMapView с пользовательской аннотацией MK

У меня есть MKMapView. Я хочу поместить пользовательскую MKAnnotation на свою карту.

Это какие-то рестораны. Как мне это сделать?

Мой вопрос: как я могу создать собственную MKAnnotation?

Спасибо, парни.


person Joaquin McCoy    schedule 15.02.2011    source источник


Ответы (2)


Во-первых, давайте определим пользовательский смысл не только в заголовке и подзаголовке. Мы хотим изменить размер MKAnnotation и включить некоторую пользовательскую графику.

Есть две части аннотации, которые вы, возможно, захотите настроить:

  • МКАннотация
  • MKAnnotationView

Для самой простой MKAnnotation вы просто примете протокол и вернете nil для заголовка и подзаголовка, но вы также можете добавить гораздо больше информации в свою аннотацию для расширенной выноски при нажатии вспомогательного индикатора. Вы можете добавить все аннотации в MKMapView, используя addAnnotation: например, в viewDidLoad.

Заголовок MKAnnotation

@interface CPAnnotation : NSObject <MKAnnotation> {
@private
    CLLocationCoordinate2D _coordinate;
    NSString *_title;
    NSString *_subtitle;
}

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, readonly, copy) NSString *title;
@property (nonatomic, readonly, copy) NSString *subtitle;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end

Реализация MKAnnotation

@implementation CPAnnotation
@synthesize coordinate = _coordinate;
@synthesize title = _title;
@synthesize subtitle = _subtitle;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
    self = [super init];

    if (self != nil) {
        self.coordinate = coordinate;
    }

    return self;
}

- (NSString *)title {
    return _title;
}

- (NSString *)subtitle {
    return _subtitle;
}
@end

Следующим шагом является настройка выноски из упавшей булавки. Для этого вам нужно настроить MKAnnotationView. По словам Apple, по умолчанию вам не следует делать огромную выноску. Они рекомендуют выноску стандартного размера с кнопкой для открытия большего размера. Они используют строчную букву i в значке синего круга. Эти значки можно установить с помощью свойств leftCalloutAccessoryView и rightCalloutAccessoryView представления. Если вы уже приняли протокол MKMapViewDelegate и установили себя в качестве делегата MKMapView, вы получите обратный вызов для viewForAnnotation:.

Обратный вызов MKAnnotationView MKMapViewDelegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *const kAnnotationReuseIdentifier = @"CPAnnotationView";

MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:kAnnotationReuseIdentifier];
if (annotationView == nil) {
    annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:kAnnotationReuseIdentifier] autorelease];
    annotationView.enabled = YES;
    annotationView.canShowCallout = YES;
    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoLight];
}

return annotationView;
}

Вы можете дополнительно настроить это в пользовательском представлении, переопределив метод drawRect, предоставив изображение для свойства изображения, или вы даже можете реализовать MKAnnotationView в XIB. Стоит немного поэкспериментировать.

Пример Apple WeatherAnnotationView иллюстрирует переопределение drawRect.

person Cameron Lowell Palmer    schedule 07.07.2012

У меня был случай, когда я хотел что-то вроде стандартной аннотации пина, но дизайнеру нужна была нестандартная графика.

Я написал подкласс MKAnnotationView для отображения графики. Единственное отличие состоит в том, что он переопределяет image стандартного класса.

BlipAnnotationView.h

#import <MapKit/MapKit.h>

@interface BlipAnnotationView : MKAnnotationView

- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier;

@end

BlipAnnotationView.m

#import "BlipAnnotationView.h"

@implementation BlipAnnotationView

- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
    if (self) {
        UIImage *blipImage = [UIImage imageNamed:@"blip.png"];
        CGRect frame = [self frame];
        frame.size = [blipImage size];
        [self setFrame:frame];
        [self setCenterOffset:CGPointMake(0.0, -7.0)];
        [self setImage:blipImage];
    }
    return self;
}

@end

Затем в классе, отображающем карту, я сделал класс, реализующий протокол MKMapViewDelegate. Метод mapView:viewForAnnotation: при необходимости создает новый экземпляр BlipAnnotationView.

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    NSLog(@"mapView:%@ viewForAnnotation:%@", mapView, annotation);
    static NSString *const kAnnotationIdentifier = @"BlipMapAnnotation";
    BlipAnnotationView *annotationView = (BlipAnnotationView *)
    [mapView dequeueReusableAnnotationViewWithIdentifier:kAnnotationIdentifier];
    if (! annotationView) {
        annotationView = [[BlipAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:kAnnotationIdentifier];
    }
    [annotationView setAnnotation:annotation];

    return annotationView;
}

Наконец, я установил класс в качестве делегата представления карты в awakeFromNib:

- (void)awakeFromNib
{
    [...]
    [_theMapView setDelegate:self];
}

Мне вообще не пришлось менять код, который позиционировал аннотацию:

MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
[annotationPoint setCoordinate:[userLocation coordinate]];
[annotationPoint setTitle:label];
[_theMapView addAnnotation:annotationPoint];
person David Hull    schedule 26.09.2012