Day 60 - 100 Days of Swift
Project 16 (part 1)
Day 60 is the first part of the sixteenth project. It is a simple little project using MapKit
to display some capitals of the world and a single fact about each of them. You get the mapView
set up, you make a custom class that conforms to MKAnnotation
, and you add some of those annotations to the map. You also adopt a couple of MKMapViewDelegate
methods to provide a custom MKAnnotationView
for the capitals and to give them a button that will display the info.
First, you make a new project, add a map view in the storyboard, constrain it, make an outlet for it, and set its delegate to be ViewController
. That gives you a basic empty map that pretty much works out of the box.

Then you add a new class that inherits from NSObject
and conforms to MKAnnotation
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import UIKit
import MapKit
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String?
init(title: String,
coordinate: CLLocationCoordinate2D,
info: String) {
self.title = title
self.coordinate = coordinate
self.info = info
}
}
Then you make a few of those in ViewContoller.viewDidLoad
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
let londonCoordinates = CLLocationCoordinate2D(latitude: 51.507222,
longitude: -0.1275)
let london = Capital(title: "London",
coordinate: londonCoordinates,
info: "Home to the 2012 Summer Olympics.")
let osloCoordinates = CLLocationCoordinate2D(latitude: 59.95,
longitude: 10.75)
let oslo = Capital(title: "Oslo",
coordinate: osloCoordinates,
info: "Founded over a thousand years ago.")
let parisCoordinates = CLLocationCoordinate2D(latitude: 48.8567,
longitude: 2.3508)
let paris = Capital(title: "Paris",
coordinate: parisCoordinates,
info: "Often called the City of Light.")
let romeCoordinates = CLLocationCoordinate2D(latitude: 41.9,
longitude: 12.5)
let rome = Capital(title: "Rome",
coordinate: romeCoordinates,
info: "Has a whole country inside it.")
let washingtonCoordinates = CLLocationCoordinate2D(latitude: 38.895111,
longitude: -77.036667)
let washington = Capital(title: "Washington DC",
coordinate: washingtonCoordinates,
info: "Named after George himself.")
And add them to the mapView
, also in viewDidLoad
:
1
mapView.addAnnotations([london, oslo, paris, rome, washington])
That leads to a map that shows pins for all the capitals we added, but not much else:

Then you adopt a MKMapViewDelegate
method that provides the view for a given annotation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func mapView(_ mapView: MKMapView,
viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard annotation is Capital else { return nil }
let identifier = "Capital"
var annotationView = mapView
.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation,
reuseIdentifier: identifier)
annotationView?.canShowCallout = true
let button = UIButton(type: .detailDisclosure)
annotationView?.rightCalloutAccessoryView = button
} else {
annotationView?.annotation = annotation
}
return annotationView
}
This makes sure that the annotation is a Capital
, tries to dequeue
a view with that identifier, and builds a new one if it can’t dequeue
one.
Then you adopt another method that is called when the callout button is tapped:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func mapView(_ mapView: MKMapView,
annotationView view: MKAnnotationView,
calloutAccessoryControlTapped control: UIControl) {
guard let capital = view.annotation as? Capital else { return }
let placeName = capital.title
let placeInfo = capital.info
let alertController = UIAlertController(title: placeName,
message: placeInfo,
preferredStyle: .alert)
let action = UIAlertAction(title: "Ok",
style: .default)
alertController.addAction(action)
present(alertController,
animated: true)
}
This just checks if the annotation is a Capital
and if it is, it presents a UIAlertController
with the information about that capital. This ends up looking like this:

You can find my version of this project at the end of day 60 on Github here.