MapKit Tutorial: Getting Started
Learn to use the powerful MapKit framework to build an interactive map, displaying location details and launching Maps for driving directions. By Andrew Tetlaw.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
MapKit Tutorial: Getting Started
35 mins
- Getting Started
- Setting the Visible Area
- Constraining the Camera
- Obtaining Public Art Data
- GeoJSON Properties
- Showing Artwork on the Map
- The Artwork Class
- Adding an Annotation
- Configuring the Annotation View
- The Map View Delegate
- Launching the Maps App
- Handling the Callout
- Setting Your Simulated Location
- Decoding GeoJSON with MKGeoJSONDecoder
- Making Annotations
- Plotting the Artwork
- Customizing Annotations
- Markers with Color-Coding and Text
- Color My World
- Annotations with Images
- Custom Callout Accessory Views
- Where To Go From Here?
MapKit is a powerful API available on iOS devices that makes it easy to display maps, mark locations, enhance with custom data and even draw routes or other shapes on top.
In this MapKit tutorial, you’ll make HonoluluArt, an app that zooms into a location in Honolulu and marks public artwork on a map. You’ll implement the marker’s callout detail button to launch the Maps app and open driving directions to the artwork. Then, you’ll parse a GeoJSON file from the Honolulu city data portal to extract the public artwork features and mark them on the map.
In the process, you’ll learn how to:
- Add a MapKit map to your app.
- Zoom to a particular location.
- Parse GeoJSON data to create custom map annotations.
Getting Started
To get started, download the starter project using the Download Materials button at the top or bottom of this tutorial. The project contains a GeoJSON file and some image assets, but no maps yet!
Open Main.storyboard and, from the Object library, drag a Map Kit View into the middle of the scene. Constrain the Map View to the super view (not the Safe Area), setting 0 on all edges, so it stretches throughout the Safe Area of notched devices.
Build and run. You now have a fully zoomable and panable map showing the continent of your current location using Apple Maps!
So far, so good, eh?
But you don’t want to start the map looking at the entire world, unless you’re a super-villain, cue evil laugh… You want to zoom into a particular area. And to do that, you need to get coding!
Open ViewController.swift and add the following below the import UIKit
statement:
import MapKit
Next, you’ll need an outlet for the MKMapView
in ViewController.swift.
Add the following outlet code immediately before viewDidLoad()
:
@IBOutlet private var mapView: MKMapView!
Then, go to Main.storyboard and link the Map View to your new outlet:
Setting the Visible Area
Go back to ViewController.swift, find viewDidLoad()
and add the following to the end of the method:
// Set initial location in Honolulu
let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)
You’ll use this to set the starting coordinates of the map view to a point in Honolulu.
When telling the map what to display, giving latitude and longitude is enough to center the map. But, you must also specify the rectangular region to display to get a correct zoom level.
Add the following private extension at the end of ViewController.swift:
private extension MKMapView {
func centerToLocation(
_ location: CLLocation,
regionRadius: CLLocationDistance = 1000
) {
let coordinateRegion = MKCoordinateRegion(
center: location.coordinate,
latitudinalMeters: regionRadius,
longitudinalMeters: regionRadius)
setRegion(coordinateRegion, animated: true)
}
}
The location
argument is the center point. The region will have north-south and east-west spans based on a distance of regionRadius
, which has a default of 1000 meters, a little more than half a mile, which works well for plotting the public artwork data in the GeoJSON file.
setRegion(_:animated:)
tells MKMapView
to display the region represented by MKCoordinateRegion
. The map view automatically transitions the current view to the desired region with a neat zoom animation, with no extra code required!
Back in viewDidLoad()
, add the following line to the end of the method:
mapView.centerToLocation(initialLocation)
This calls the helper method to zoom into initialLocation
on startup.
Build and run. You’ll find yourself in the heart of Waikiki. Aloha! :]
Constraining the Camera
So far, you’ve been able to go anywhere you want on the map, but we’re only interested in the island of Oahu. You’ve also been able to pinch in to zoom the map so far that the island is only a few pixels! MapKit is capable of constraining the user to pan and zoom the map over a specified area.
Once again in viewDidLoad()
, add the following lines to the end of the method:
let oahuCenter = CLLocation(latitude: 21.4765, longitude: -157.9647)
let region = MKCoordinateRegion(
center: oahuCenter.coordinate,
latitudinalMeters: 50000,
longitudinalMeters: 60000)
mapView.setCameraBoundary(
MKMapView.CameraBoundary(coordinateRegion: region),
animated: true)
let zoomRange = MKMapView.CameraZoomRange(maxCenterCoordinateDistance: 200000)
mapView.setCameraZoomRange(zoomRange, animated: true)
Build and run. Now when you zoom out, you can’t make Oahu as small as before. You can only pan the map view to see the northern, southern, eastern and westernmost edges of the island.
MapKit uses an internal camera to determine where the point of view for the map is, how expansive the field of view is and to animate view movement. When you specify a camera boundary with a center and a region rectangle, the camera center always stays within this region.
If the user tries to pan further out of the region, the view doesn’t scroll any further. It keeps them focused on the area you want them to see. A region size of 60,000 meters wide by 50,000 meters high keeps Oahu nicely constrained within the map view.
The MapKit view camera keeps track of its distance from the view center when zooming in and out. Setting the camera zoom range maximum center distance constraint limits how far the view zooms out and how tiny the island of Oahu becomes. This is even more helpful when adding points of interest to the map, which is the next step!
Obtaining Public Art Data
The next step is to plot interesting data around the current location. But where in the world can you get such stuff?
Well, it depends on your current location. Honolulu, like many cities, has an Open Data Portal to improve public access to government data.
One convenient feature of Honolulu’s data portal is the ability to export the data set in GeoJSON format — a flavor of JSON that’s used to represent geospatial features along with their metadata. One of MapKit’s recent features makes it super-easy to use GeoJSON data in your app, as you’ll soon see.
For this tutorial, you’ll use the Honolulu Public Art dataset. To keep things simple, I’ve already exported this data from the portal and included it in the starter project, nicely formatted for readability, of course. It’s the least I could do.
To get a feeling for the items in this dataset, open PublicArt.geojson in the Xcode editor. At the top level you’ll see:
{
"type": "FeatureCollection",
"features": [ ... ]
}
The value for the key features
is an array of GeoJSON objects of the type Feature
. Each one of these objects contains some standard keys, but also a properties
dictionary with some custom fields created by the data portal. The geometry
key is where you’ll find the coordinates of the feature.
Have a look at the first one:
{
"type":"Feature",
"properties":{
"location":"Lester McCoy Pavilion",
"latitude":"21.290824",
"description":"...",
"thumb":null,
"credit":"Funded by the Works Progress Administration",
"objectid":"1930.01.01",
"creator":"Robert Lee Eskridge",
"longitude":"-157.85131",
"imagefile":"http://....JPG",
"date":"1935",
"discipline":"Mural",
"title":"The Makahiki Festival - The Makai Mural",
"access":"Limited"
},
"geometry":{
"type":"Point",
"coordinates":[-157.85131,21.290824]
}
}