iOS

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

We use Xcode 4.5 to create the project. If you’re using lower version of Xcode, some of the screens you’ll see may be slightly differed.

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

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”.

MyLocationMap Embed Navigation Bar

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.

MyLocationMap Add Map View

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.

MyLocationMap Add Framework

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.

MyLocationMap 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.

MyLocationMap App Fake Location

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:

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:

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)

MyLocationMap MapView Variable

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:

Also, add the didUpdateUserLocation method:

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:

MyLocationMap Zoom In

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:

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.

Xcode Simulate Location

Simulate Other Locations

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

MyLocationMap Final Deliverable

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.

iOS
How To Add a Slide-out Sidebar Menu in Your Apps
iOS
A Beginner’s Guide to Auto Layout with Xcode 8
iOS
Core Image Introduction: Applying Image Filters to Photos
  • rawnwolf

    rawnwolfrawnwolf

    Author Reply

    Another 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

    Awesome! Very cool new tutorial. Thanks for all the effort you put into this 🙂


  • 망각인간

    Thank 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

    thanks once again….great article as always…


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Great to hear that! Thanks.


  • waldorfian

    waldorfianwaldorfian

    Author Reply

    I’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

    Hi,
    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

      Simon NgSimon Ng

      Author Reply

      You can use the following code instead of “addAnnotation”:
      [self.mapView selectAnnotation:point animated:YES];


  • smashingpuffins

    I’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

    AxelAxel

    Author Reply

    Nice 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

    SourabhSourabh

    Author Reply

    Awsm tutorial for a beginner….Thanx for dis


  • Ravikumar

    RavikumarRavikumar

    Author Reply

    its an excellent tutorial for ios people


  • João R Watter Jr.

    Is 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

      Hey, did you found a way to solve that? I’d like to know about this too..


  • Giancarlo Leonio

    Thank 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

    can 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

      Its ok, I was able to copy and paste it and it gave me all the code.


      • Master Mj

        Master MjMaster Mj

        Author Reply

        Okay just realised you are sorted now!


  • Master Mj

    Master MjMaster Mj

    Author Reply

    Loved it for days! Thanx mate!!! Keep em rolling, and we will keep clicking (your ads)


  • Master Mj

    Master MjMaster Mj

    Author Reply

    David, copy and paste the code, had a similar problem , just paste onto a notepad (developers’ dream)


  • Master Mj

    Master MjMaster Mj

    Author Reply

    Love your work guys, honestly have you to thank for alot of what I know now!


  • bourbon

    bourbonbourbon

    Author Reply

    Thanks 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

    JackJack

    Author Reply

    Thanks 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

    Thanks


  • Tom

    TomTom

    Author Reply

    Does 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

    Sipho KozaSipho Koza

    Author Reply

    Hi, 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

    Is 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

    HusamHusam

    Author Reply

    Simple and useful … thanks4u


  • Mills Joshi

    Simply awesome 🙂


  • Sandip

    SandipSandip

    Author Reply

    Thanx 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

    RobRob

    Author Reply

    You should do one to track speed and distance 🙂 But very great tutorial! Worked first try


  • ShanghaiTimes

    Great 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

    s 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

    Well, 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

    I 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

    OK – 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

    annotation is not showing


  • Steven

    StevenSteven

    Author Reply

    That 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

    tomathenstomathens

    Author Reply

    Hi. 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

    UmarUmar

    Author Reply

    This Tutorial very helpful for beginners like me..thanks appcoda


  • martin

    martinmartin

    Author Reply

    simple and humble .


  • pentool

    pentoolpentool

    Author Reply

    In 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

    UpendraUpendra

    Author Reply

    great…!!


  • Upendra

    UpendraUpendra

    Author Reply

    can we show two different pin with different colour…??


  • Rodiyan Gibran Sentanu

    Hi, 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

    thanks for this wonder full example code


  • chotspric .

    Hi, 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

    very nice and simple tutorial


  • wilson

    wilsonwilson

    Author Reply

    Great tutorial. Simple, but good enough.


  • Donovan Webb

    great tutorial, how do you delete the pin


  • Emmanuel Texis

    Why when i use the same code in Swift it simply does nothing?


  • Rahul Mishra

    pin is working fine but i am not able to show the title


  • guest4u

    guest4uguest4u

    Author Reply

    Would love to see this tutorial updated for iOS8!


  • Ayush Gupta

    Hi thnx for this gr8 tutorial.And how to implement auto zoom to the pinned location.Thnx


  • Ankit

    AnkitAnkit

    Author Reply

    ” 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

    SASI KUMARSASI KUMAR

    Author Reply

    Hi,


  • SASI KUMAR

    SASI KUMARSASI KUMAR

    Author Reply

    I 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

    2015-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

      In 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.


Shares