У меня есть MKMapView. Я хочу поместить пользовательскую MKAnnotation на свою карту.
Это какие-то рестораны. Как мне это сделать?
Мой вопрос: как я могу создать собственную MKAnnotation?
Спасибо, парни.
У меня есть MKMapView. Я хочу поместить пользовательскую MKAnnotation на свою карту.
Это какие-то рестораны. Как мне это сделать?
Мой вопрос: как я могу создать собственную MKAnnotation?
Спасибо, парни.
Во-первых, давайте определим пользовательский смысл не только в заголовке и подзаголовке. Мы хотим изменить размер MKAnnotation и включить некоторую пользовательскую графику.
Есть две части аннотации, которые вы, возможно, захотите настроить:
Для самой простой MKAnnotation вы просто примете протокол и вернете nil для заголовка и подзаголовка, но вы также можете добавить гораздо больше информации в свою аннотацию для расширенной выноски при нажатии вспомогательного индикатора. Вы можете добавить все аннотации в MKMapView, используя addAnnotation: например, в viewDidLoad.
@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
@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 *)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.
У меня был случай, когда я хотел что-то вроде стандартной аннотации пина, но дизайнеру нужна была нестандартная графика.
Я написал подкласс MKAnnotationView
для отображения графики. Единственное отличие состоит в том, что он переопределяет image
стандартного класса.
#import <MapKit/MapKit.h>
@interface BlipAnnotationView : MKAnnotationView
- (id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier;
@end
#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];