iOS Programming 101: Intro to MapKit API and Add an Annotation on Map
A month ago, we covered how to use Core Location framework to retrieve the user’s location. We also showed you how to convert the GPS coordinate into an address. However, the best way to show a location is to pin it on map. Thanks to the MapKit API. It lets programmers easily work with the built-in Maps and pin a location.
The Map Kit framework provides an interface for embedding maps directly into your own windows and views. This framework also provides support for annotating the map, adding overlays, and performing reverse-geocoding lookups to determine placemark information for a given map coordinate.
– iOS Developer Reference
MapKit is a neat API, comes with the iOS SDK, that allows you to display maps, navigate through maps, add annotations for specific locations, add overlays on existing maps, etc. In this tutorial, we’ll walk you though the basics of the API and show you how to place a pin on the map. As usual, rather than going through the theory, we’ll work on a simple app. Through the practice, we hope you’ll get a better idea about MapKit.
Let’s get started.
Create the Project and Design the Interface
First, create a new Xcode project using the Single View Template. Let’s name the project as “MyLocationMap” and set the project with the following parameters:

MyLocationMap Xcode Project
Once you successfully created your project, go to the Storyboard and design the user interface. We want to embed the view controller in a navigation controller. First, select the view controller and select “Editor” -> “Embed in” -> “Navigation Controller”.

Embed View Controller in Navigation Controller
Optionally, you can set the title of the navigation bar. Say, let’s name it as “My Maps”. Finally, drag a Map View from Object Library to the view controller. In the Attribute Inspector of Map View, check the “Show User Location” option. By enabling user location, the map automatically shows the current location of the user.

Add Map View to View Controller
As the app makes use of the Core Location and MapKit frameworks, add these two frameworks to our project. Select “MyLocationMap” in the Project Navigator, followed by the “MyLocationMap” under Targets. Then select “Build Phases” and expand “Link Binary with Libraries”. Click the “+” button to add both “CoreLocation” and “MapKit” frameworks.

Add CoreLocation and MapKit Frameworks
Till now, we haven’t written a line of code. Before moving on, let’s run the app and see how it looks like.
As soon as the app launches, it prompts you to access the location service. Just tap “OK” to permit it to use the current location. You’ve already built a Maps app.

Do you still remember how to test a location aware app using the iOS Simulator? Recalled that the iOS Simulator lets you fake a location, you can select “Debug” -> “Location” in the menu bar. Change the location from “None” to “Apple”. You’ll then see a blue dot that indicates the current location on map.

Test Current Location with Fake Location
Cool, right? We haven’t covered the coding part. What we’ve done so far is simply drag & drop of the UI component and we’ve displayed the current location on map.
Zoom Into the Current Location
Does our tutorial end here? Of course not. We still got a lot to discuss. One thing is the scale of the map. It’s now showing the entire world. Normally you don’t want to display the current location in such scale, but zoom into the particular area.
Okay, let’s get back to code.
First, we create an outlet in “MyLocationViewController.h” and establish a connection with the Map View. In “MyLocationViewController.h”, declares the “mapView” property and implements the MKMapViewDelegate protocol. Your code should look like below:
1 2 3 4 5 6 7 8 |
#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> @interface MyLocationViewController : UIViewController <MKMapViewDelegate> @property (nonatomic, strong) IBOutlet MKMapView *mapView; @end |
Let’s forget about the MKMapViewDelegate, for which we’ll look into later. Next, go to the “MyLocationViewController.m” file and add the synthesis statement:
1 2 3 4 5 6 7 8 9 10 |
@interface MyLocationViewController () @end @implementation MyLocationViewController @synthesize mapView; . . . |
Lastly, go back to the Storyboard and connect the mapView variable with the Map View component. (Press and hold the Control key on your keyboard, click the “File Owner” icon and drag to the Map View)

Establish Connection with Map View
Now, let’s get back to the MKMapViewDelegate protocol. What’s it for? Why do we need to use it? Technically, the MKMapViewDelegate protocol defines a set of optional methods that you can use to receive map-related update messages. For example, you go for a run with your iPhone. Your location keeps changing during your run. To receive the location change/update, you can implement the protocol. The mapView:didUpdateUserLocation method is called whenever a new location update is received by the map view.
This is one of the examples you’ll implement the MKMapViewDelegate protocol. You can also make use of it to change the annotation view that we’ll demonstrate in later tutorials.
Go back to the “MyLocationViewController.m” and update the “viewDidLoad” method to assign the delegate of mapView:
1 2 3 4 5 |
- (void)viewDidLoad { [super viewDidLoad]; self.mapView.delegate = self; } |
Also, add the didUpdateUserLocation method:
1 2 3 4 5 |
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800); [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES]; } |
The above lines of code instructs the map view to zoom into a region that is 800 by 800 meters around the user’s location.
Run the app again, set the location to Apple’s headquarter. Now the map automatically updates to our preferred scale:

Adding an Annotation to Map
As you can see from the above screenshots, the current user’s location is indicated as a blue dot. We want to change it and place a pin onto the map.
According to iOS developer guide, in order to display an annotation on a map, your app must provide two distinct objects:
- An object that conforms to the MKAnnotation protocol and manages the data for the annotation. (This object is the annotation object.)
- A view (derived from the MKAnnotationView class) used to draw the visual representation of the annotation on the map surface. (This is the annotation view.)
The iOS comes with a built-in annotation object – MKPointAnnotation. This object already provides concrete implementation of the MKAnnotation protocol. You can make use of this simple objects, rather than define your own, whenever you want to associate a point on the map with a title.
In this tutorial, we keep thing simple and utilize the MKPointAnnotation object to associate with the user’s location. Update the “didUpdateUserLocation” method to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800); [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES]; // Add an annotation MKPointAnnotation *point = [[MKPointAnnotation alloc] init]; point.coordinate = userLocation.coordinate; point.title = @"Where am I?"; point.subtitle = @"I'm here!!!"; [self.mapView addAnnotation:point]; } |
To place a pin in the correct location on map, we first create a MKPointAnnotation object and assign it with the coordinate of user’s location. We also assign the title and subtitle for the call-out that appears when you tap on the pin. Lastly, we call the addAnnotation: method to add the annotation object to the map view.
Test the App Again
As you run the app again, it places a pin over the current location. Tapping on the pin brings up the call-out showing “Where am I?” and “I’m here!!!”.
While running the app, try to change to other locations by using the arrow button in the top bar of the debug area.

Simulate Other Locations
As soon as the location is changed, your app instantly updates the user’s location.

MyLocationMap – Switch Your User's Location
Summary
In this tutorial, we introduce the basics of MapKit API and walked you through how to show user’s location on the map. You also learnt how to put a pin (i.e. annotation) to indicate a location.
What do you think about this tutorial? As always, we love to hear your feedback.
Comments
rawnwolf
AuthorAnother great tutorial! Thank you! I always look forward to seeing a new email from appcoda.com telling me there is another great tutorial online!
I am hoping that you will do another tutorial soon. I can’t seem to find a tutorial online anywhere that shows how to move a picture using the gyroscope (like the Apps for Tour Wrist and 360 Pano)…maybe you will do one? (please, please, please!)
Jan Brinkmann
AuthorAwesome! Very cool new tutorial. Thanks for all the effort you put into this 🙂
망각인간
AuthorThank you for your lecture.
Practice have been informative lecture today.
To your request.
Be customized to address specific areas of the map to show how to tell?
Malkit Singh
Authorthanks once again….great article as always…
Simon Ng
AuthorGreat to hear that! Thanks.
waldorfian
AuthorI’m just wondering why you reference the viewcontroller by a different name. you didn’t specify that you changed the name and by default its called simply viewcontroller.
Marcos Vilela
AuthorHi,
Is there anyway to make the title and subtitle always visible? I mean, I don’t wanna have to tap on the pin to see title and subtitle.
thanks,
Marcos Vilela.
Simon Ng
AuthorYou can use the following code instead of “addAnnotation”:
[self.mapView selectAnnotation:point animated:YES];
smashingpuffins
AuthorI’ve been trying to accomplish this for weeks, thank you sooooo much! not only was this tutorial easy to follow it was very informative as well, I wish other tutorials were as good.
Axel
AuthorNice Work!! Great tutorial! I want the user to add the PIN in any location on the map, and let him add some title and subtitle, is that possible ???
Sourabh
AuthorAwsm tutorial for a beginner….Thanx for dis
Ravikumar
Authorits an excellent tutorial for ios people
João R Watter Jr.
AuthorIs there some way to save the MKMapView object to a jpg file. I mean I’d like to save the zoomed map to a file. Is it possible?
Natan Magalhaes
AuthorHey, did you found a way to solve that? I’d like to know about this too..
Giancarlo Leonio
AuthorThank you for this tutorial. I found it really helpful in adding custom annotations to my MapView control. I made a list of top resources on map annotation tutorials. I included this post. Hope it can be useful to other developers. Check it out, feel free to share 🙂
http://www.verious.com/board/Giancarlo-Leonio/map-annotation-for-ios
Davie Smith
Authorcan anyone help? the end of the code is cut of on this page and I’m not sure what to put, I’ve had a couple of guesses and am getting errors.
Davie Smith
AuthorIts ok, I was able to copy and paste it and it gave me all the code.
Master Mj
AuthorOkay just realised you are sorted now!
Master Mj
AuthorLoved it for days! Thanx mate!!! Keep em rolling, and we will keep clicking (your ads)
Master Mj
AuthorDavid, copy and paste the code, had a similar problem , just paste onto a notepad (developers’ dream)
Master Mj
AuthorLove your work guys, honestly have you to thank for alot of what I know now!
bourbon
AuthorThanks for this great example… I have a little question, if i want store that annotation or annotations on the map.. How can i store in core data? i have a simple application, it takes some datas. Can anyone help me ? thanks..
Jack
AuthorThanks for all the great tutorials!!! They’re really helpful for beginners…
Just one thought, how about a tutorial in which we learn how to customize a pin, and create our own annotation object.
i.e.: coloring the pins and replacing the MKPointAnnotation with a custom view that contains an image, title, subtitle and an additional label for perhaps flying distance from current location.
I also have a question: how can we get touch info from the the map (in GPS coordinates) so we can add a pin on touch?
Thanks again and keep up the good work 🙂
Ganesh Auti
AuthorThanks
Tom
AuthorDoes anyone have any idea why this would run on the iOS simulator, but then crash on my actual device? It works fine up until I try to add the function to zoom to the location. I looked with the debugger and it actually does execute the didUpdateUserLocation function, but crashes sometime while returning from the function. The debugger goes into some assembly code after the function so I’m not exactly sure where it crashes. It’s just very strange since it works on the simulator.
Sipho Koza
AuthorHi, I’m actually new in Mobile development. But i actually wanna create an application using mapKit and be able to type in a textfield and look for a particular location or a retail shop around my area. Thanks in advance!!!
Osvaldo Cipriano
AuthorIs it possible that you make a tutorial like this one but with another anotation and a field to show the distance between the anotation and our current location?
Husam
AuthorSimple and useful … thanks4u
Mills Joshi
AuthorSimply awesome 🙂
Sandip
AuthorThanx a lot friend this helps me to understand Map kit in ios….
now i want to add some addition functionality like draw rout between two point of location
Do you about any tutorial that can help me to do this
thank you
Rob
AuthorYou should do one to track speed and distance 🙂 But very great tutorial! Worked first try
ShanghaiTimes
AuthorGreat tutorial guys. Is there any plans to upgrade this to iOS7/XCode 5? It works pretty much as is, but there are a few things that need changing.
ShanghaiTimes
Authors you can see – it’s working well. Took me a little time to work out how the Map object dragged onto the View – NOT the Navigator. Then it worked fine.
Most excellent tutorials. Clear and concise.
ShanghaiTimes
AuthorWell, right at the end of the tutorial – adding the pin and the annotation – I don’t get the annotation showing up.
When the simulator first starts – it’s moving slightly, and leaves a trail of pins across the map. Then, when I set a new location, it stops that behaviour, shows the single pin – but no annotation. Obviously something different with this latest version of XCode5/iOS7
ShanghaiTimes
AuthorI added comments to the MapKit 101 Tutorial so I won’t add it all here again. Not getting the annotation showing up. Running XCode5/iOS7 – otherwise all works well.
ShanghaiTimes
AuthorOK – mea culpa. Before you read any further, it actually is working kind of. After setting a location in XCode Debug, up pops the flashing dot, click on the dot and it displays [Current Location] click again, and it then says – [Where am I – here I am ] or what ever text you have in the string.
If you have no location set for it to go to, the red pin starts to animate across the display… until you go back to xcode and set a location.
but hey. took me two days to discover that quite by accident.
Deepak Kumar Arya
Authorannotation is not showing
Steven
AuthorThat was a great tutorial. Although reading documentation is important, I learned in your tutorial in 20 minutes what I spent 1 hour looking for in the documentation. Thank you.
tomathens
AuthorHi. I spent a lot of time searching for an issue I cannot solve, and it should be not that hard. I would like the annotation be dropped automatically with the pin. This is so commen but I do not know how to make it. I can only make the map with the pin being dropped. Does anyone know how the annotation can be dropped also? Thanks so much.
Umar
AuthorThis Tutorial very helpful for beginners like me..thanks appcoda
martin
Authorsimple and humble .
pentool
AuthorIn the code sample box, you write:
MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
I am puzzled as to where and how did you get a ‘coordinate’ from ‘userLocation’? According to the docs (Xcode 5.1.1) MKUserLocation object has no property that’s called ‘coordinate’. Oddly enough, however, according to the code hint it does, and it compiles and runs fine. Would the documentation be incomplete or am I just overlooking something?
(…thanks for the tut,BTW!)
Upendra
Authorgreat…!!
Upendra
Authorcan we show two different pin with different colour…??
Rodiyan Gibran Sentanu
AuthorHi, thanks for this tutorial.
I have a question actually. I already follow your code, but my app don’t want to zoom in into user location.
can you tell me why?
girish chauhan
Authorthanks for this wonder full example code
chotspric .
AuthorHi, I am following several tutorials about the iOS Mapkit framework.
I live in Portugal, and the city of Lisbon has many web services we can use, but I found myself in a big issue:
i.e (if I try to use one of the web services api they have at:
http://digc.cm-lisboa.pt/DIGC/rest/services/OpenDataLX/LxPOI/MapServer
and if I choose i.e. option /116/1 that stands for “traditional coffee shops” and get the first item
http://digc.cm-lisboa.pt/DIGC/rest/services/OpenDataLX/LxPOI/MapServer/116/1
Just take a look at the geo coordinates….
What the hell is Point:
X: -1024499,0043
Y: 4678426,5468
if I try to draw it on the map it doesn’t correspond to the real Lat Long for that coffee shop.
Take a closer look at this link:
http://digc.cm-lisboa.pt/DIGC/rest/services/OpenDataLX/LxPOI/MapServer/116
Geometry Type: esriGeometryPoint
Extent:
XMin: -1028372.32756313
YMin: 4676782.25640479
XMax: -1011303.94154349
YMax: 4693079.50182223
Spatial Reference: 102113
My question:
Do we have to work with ArcGIS Runtime SDK for iOS in order to plot esri points x,y ?
i.e.
// Implement viewDidLoad to do additional setup after loading the view
– (void)viewDidLoad {
[super viewDidLoad];
NSURL *mapUrl = [NSURL URLWithString:@”http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer”];
AGSTiledMapServiceLayer *tiledLyr = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:mapUrl];
[self.mapView addMapLayer:tiledLyr withName:@”Tiled Layer”];
AGSSpatialReference *sr = [AGSSpatialReference spatialReferenceWithWKID:102113];
AGSEnvelope *env = [AGSEnvelope envelopeWithXmin:-1028372.32756313 ymin:4676782.25640479 xmax:-1011303.94154349 ymax:4693079.50182223 spatialReference:sr];
[self.mapView zoomToEnvelope:env animated:YES];
}
Sarin sukumar
Authorvery nice and simple tutorial
wilson
AuthorGreat tutorial. Simple, but good enough.
Donovan Webb
Authorgreat tutorial, how do you delete the pin
Emmanuel Texis
AuthorWhy when i use the same code in Swift it simply does nothing?
Rahul Mishra
Authorpin is working fine but i am not able to show the title
guest4u
AuthorWould love to see this tutorial updated for iOS8!
Ayush Gupta
AuthorHi thnx for this gr8 tutorial.And how to implement auto zoom to the pinned location.Thnx
Ankit
Author” Do you still remember how to test a location aware app using the iOS Simulator? Recalled that the iOS Simulator lets you fake a location, you can select “Debug” -> “Location” in the menu bar. Change the location from “None” to “Apple”. You’ll then see a blue dot that indicates the current location on map. ”
this part does not work in Xcode 6
plzz suggest amends … asap
SASI KUMAR
AuthorHi,
SASI KUMAR
AuthorI followed ur code and add that to my module .The image view size smal .iIt take only 25% of screen.I cant get User location Icon.Will u try to help me
Parag Bharambe
Author2015-12-22 19:06:42.646 MyLocationMap[3870:97722] Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
i’m getting these 2 error plz help
Ranjeet Singh
AuthorIn iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start. There are two Info.plist keys for the new location authorization. One or both of these keys is required. If neither of the keys are there, you can call startUpdatingLocation but the location manager won’t actually start. It won’t send a failure message to the delegate either (since it never started, it can’t fail). It will also fail if you add one or both of the keys but forget to explicitly request authorization.
So the first thing you need to do is to add one or both of the following keys to your Info.plist file:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Both of these keys take a string which is a description of why you need location services. You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.
Next you need to request authorization for the corresponding location method, WhenInUse or Background. Use one of these calls:
In .h file create the CLLocation manager property
than put
these two lines in .m view did load.
[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]
Cheers.
Anamta Aasim
AuthorAnd what do we do in swift?
Ranjeet Singh
AuthorI believe steps should be same , only syntax differs