iOS Programming 101: Intro to MapKit API and Add an Annotation on Map

54 Flares 54 Flares ×

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:

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)

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:

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:

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:

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.

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.

You May Like These:

Get Free Chapters of Our Swift Book

Beginning iOS 8 Programming with SwiftIf you want to create an app but don't know where to begin, this book covers the whole aspect of Swift programming and iOS 8 development and shows you every step from an idea to a real app on App Store. This book features a lot of hands-on exercises and projects. You will first create a simple app, then prototype an app idea, and later add some features to it in each chapter, until a real app is built. Want to learn more? Check it out here and get three free chapters.


  • rawnwolf

    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!)

  • http://www.facebook.com/luckyduck.networks Jan Brinkmann

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

  • http://twitter.com/minasememory 망각인간

    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…

    • http://www.simonblog.com Simon Ng

      Great to hear that! Thanks.

  • waldorfian

    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.

  • http://twitter.com/vilelamarcos 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.

    • http://www.simonblog.com Simon Ng

      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

    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

    Awsm tutorial for a beginner….Thanx for dis

  • Ravikumar

    its an excellent tutorial for ios people

  • http://twitter.com/jrwatter 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?

    • http://www.facebook.com/natanmagalhaes 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

  • Pingback: mapkit link | ladaninikunj1

  • Pingback: mapkit link | jaydeepkamani1

  • Pingback: mapkit link | jaydeepkamani1

  • 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

        Okay just realised you are sorted now!

  • Master Mj

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

  • Master Mj

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

  • Master Mj

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

  • bourbon

    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

    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

    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

    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

    Simple and useful … thanks4u

  • Mills Joshi

    Simply awesome :)

  • Sandip

    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

    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.

  • http://twitter.com/ShanghaiTimes 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.

  • http://twitter.com/ShanghaiTimes 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

  • http://twitter.com/ShanghaiTimes 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.

  • http://twitter.com/ShanghaiTimes 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

    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

    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

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

  • martin

    simple and humble .

  • pentool

    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

    great…!!

  • Upendra

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

  • Pingback: hometownledners

  • 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

    Great tutorial. Simple, but good enough.

  • http://egsforever.playat.ch/wordpress/ Donovan Webb

    great tutorial, how do you delete the pin

  • Pingback: Top 5 Mapkit tutorial for iOS | Mobile Dev Resources

  • Emmanuel Texis

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

54 Flares Twitter 5 Facebook 45 Google+ 3 LinkedIn 1 54 Flares ×