Skip to content

Using MKAnnotation, MKPinAnnotationView and creating a custom MKAnnotationView in an MKMapView

My last experiment maps on the iPhone using the MKMapView from the iPhone’s MapKit was an example of how to use the MKMapView to display the line of a route on the map.

Today’s experiment will demonstrate how to drop pin annotation views, as well as custom annotation views on the iphone’s map by providing the map with objects that implement the MKAnnotation protocol.

The class I created that implements MKAnnotation can be used to differentiate between those annotations that should be represented by MKPinAnnotationViews of diferernt colors, as well as our custom annotation view, CSImageAnnotationView. The CSMapAnnotation class needs to keep track of additional information such as images and URLs that can be used for a custom display.

This is the header for the custom annotation. You can see that there is an enumeration that is used to designate what type of annotation view should be used for display of each annotation on the iPhone’s map. Also available are the userData and url properties; userData can be used to store anything, but in the case of this example, we’re using it to store path information for an image that should be displayed on the map. Title is also an available property, but subtitle will be generated on the fly.

// CSMapAnnotation.h
// mapLines
// Created by Craig on 5/15/09.
// Copyright 2009 Craig Spitzkoff. All rights reserved.


// types of annotations for which we will provide annotation views.
typedef enum {
CSMapAnnotationTypeStart = 0,
CSMapAnnotationTypeEnd = 1,
CSMapAnnotationTypeImage = 2
} CSMapAnnotationType;

@interface CSMapAnnotation : NSObject
CLLocationCoordinate2D _coordinate;
CSMapAnnotationType _annotationType;
NSString* _title;
NSString* _subtitle;
NSString* _userData;
NSURL* _url;

-(id) initWithCoordinate:(CLLocationCoordinate2D)coordinate
annotationType:(CSMapAnnotationType) annotationType

@property CSMapAnnotationType annotationType;
@property (nonatomic, retain) NSString* userData;
@property (nonatomic, retain) NSURL* url;


In most cases, when our MKMapViewDelegate is asked for an MKAnnotation, we return a MKPinAnnotation. If the CSMapAnnotation is set to be CSMapAnnotationTypeImage , the delegate instead produces an instance of our custom annotation view, CSImageAnnotationView, and sets its properties based on the annotation’s user data.

This is the body of our custom annotation view. It is pretty simple; the bulk of the functionality is in the initialization function, which sets up the view to have a UIImageView.

// CSImageAnnotationView.m
// mapLines
// Created by Craig on 5/15/09.
// Copyright 2009 Craig Spitzkoff. All rights reserved.

#import "CSImageAnnotationView.h"
#import "CSMapAnnotation.h"

#define kHeight 100
#define kWidth 100
#define kBorder 2

@implementation CSImageAnnotationView
@synthesize imageView = _imageView;

- (id)initWithAnnotation:(id )annotation reuseIdentifier:(NSString *)reuseIdentifier
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
self.frame = CGRectMake(0, 0, kWidth, kHeight);
self.backgroundColor = [UIColor whiteColor];

CSMapAnnotation* csAnnotation = (CSMapAnnotation*)annotation;

UIImage* image = [UIImage imageNamed:csAnnotation.userData];
_imageView = [[UIImageView alloc] initWithImage:image];

_imageView.frame = CGRectMake(kBorder, kBorder, kWidth - 2 * kBorder, kWidth - 2 * kBorder);
[self addSubview:_imageView];

return self;


-(void) dealloc
[_imageView release];
[super dealloc];


So, how does the map know to ask the delegate for annotation views? It knows to do this based on annotations that are added to the map in our view controller’s viewDidLoad method.

// create the image annotation
annotation = [[[CSMapAnnotation alloc] initWithCoordinate:[[points objectAtIndex:points.count / 2] coordinate]
title:@"Cleveland Circle"] autorelease];
[annotation setUserData:@"cc.jpg"];
[annotation setUrl:[NSURL URLWithString:@""]];

[_mapView addAnnotation:annotation];

UPDATE – 6/1/2009
You’ll notice we set the URL on the annotation above, and the code has now been updated to display that webpage when the user clicks the annotation disclosure of our custom image annotation view. The code sample you can download has been updated to reflect this change.

The full code of this example is available for download here.

Update – 8/19/2009
Another update. This one displays the route as an annotation view, so it does not render on top of other annotations.You can view the update at this link.

{ 8 } Comments

  1. Bones | August 27, 2010 at 12:21 pm | Permalink

    Great Tutorial, I learned a lot. I did find an issue with the custom pin. The pin drops on a location, but the pin needle is not the spot that gets converted to Long/Lat. If the user drops the pin, the long lat is off by the size of the Pin.png. The Pin head is what converted to long lat.

    Also, I was curious as to why you choose to use Notification when you could have past a mapView reference to update the pin location?

    Like I said, great tutorial – just some questions and observations.


  2. drVacansS | October 22, 2010 at 1:00 am | Permalink

    В наше время, очень тяжело найти хорошую работу, с достойной заработной платой. Не отчаивайтесь, посмотрите в наших базах. Мы собираем только лучшие вакансии, на рынке труда России.

    [URL=]Работа в маскве[/URL] [URL=]Работа сварщиком в москве[/URL] [URL=]Работа для иногородних в москве[/URL] [URL=]Предложение вакансий[/URL] [URL=]Работа сегодня вакансии[/URL] [URL=]работа для девушек в москве[/URL] [URL=]Работа в королеве мытищах[/URL] [URL=]Вакансии вахтовым методом в москве[/URL] [URL=]Работа север вахта[/URL] [URL=]Работа супервайзер[/URL]

    Не откладывайте на завтра то, что можно сделать сегодня. Трудись как муравей, если хочешь быть уподоблен пчеле. Бездельник не имеет право сказать, что живет. Ничто в жизни не достается без труда. Для бездельника жизнь скучна, а для делового – радость. Только труд дает право на наслаждение. Труд – основа жизни. Трудолюбивая пчела умеет собрать мед и с горьких цветов.

    [URL=]Работа в королеве мытищах[/URL] [URL=]работа для девушек в москве[/URL] [URL=]Работа сегодня вакансии[/URL] [URL=]Работа сварщиком в москве[/URL] [URL=]Работа в маскве[/URL] [URL=]Предложение вакансий[/URL] [URL=]Работа север вахта[/URL] [URL=]Работа для иногородних в москве[/URL] [URL=]Работа супервайзер[/URL] [URL=]Вакансии вахтовым методом в москве[/URL]

  3. Player Profiles | October 30, 2010 at 5:57 am | Permalink

    Best you could edit the page title The Reluctant Blogger : Using MKAnnotation, MKPinAnnotationView and creating a custom MKAnnotationView in an MKMapView to something more catching for your content you create. I enjoyed the the writing even sononetheless.

  4. Dario Rinks | July 25, 2011 at 7:00 pm | Permalink

    Nice job, it is a fantastic post. The information is very good to know!

  5. LeBzul | January 10, 2012 at 4:50 am | Permalink

    Thank !

    I think :
    _imageView.frame = CGRectMake(kBorder, kBorder, kWidth – 2 * kBorder, kWidth – 2 * kBorder);

    It’s :
    _imageView.frame = CGRectMake(kBorder, kBorder, kWidth – 2 * kBorder, kHeight – 2 * kBorder);

  6. Carly Rae Jepsen Sex Tape | July 24, 2012 at 1:32 pm | Permalink

    you|and allow you to} know how {much|great|really|, very

  7. maquanhong | November 22, 2013 at 3:53 am | Permalink

    Thanks very much,I have trapped in the question which is I can’t add a button on BMKAnnotationView(baidu map) for a lone time. Final,I found the answer here.

  8. Ali | February 21, 2014 at 10:10 am | Permalink

    Thank you very much this was very helping.

Post a Comment

Your email is never published nor shared. Required fields are marked *