Follow along at https://www.hackingwithswift.com/100/60.
This day covers the first part of
Project 16: Capital Cities
in Hacking with Swift.I previously created projects alongside Hacking with Swift in a separate repository, and you can find Project 16 here. Even better, though, I copied it over to Day 60's folder so I could extend it for 100 Days of Swift.
With that in mind, Day 60 focuses on several specific topics:
- Up and running with MapKit
- Annotations and accessory views: MKPinAnnotationView
To place annotations on a map, we need annotation objects and annotation views.
Making annotation objects is rather straightforward. Objects need to be subclasses of NSObject
that conform to the MKAnnotation
protocol — which means they need to contain a coordinate
and, optionally, a name
and subtitle
.
When these objects are loaded in our view controller, we can grab an outlet to a map view and start annotating:
mapView.addAnnotations(annotations)
With a view controller that conforms to MKMapViewDelegate
, and registers as a delegate
of an MKMapView
instance, we get notified when that instance loads the map, add annotations, reveals annotation overlays, and more.
Again, the consistent delegation patterns of Apple's APIs allow us to interact with underlying parts of our app in a familiar way. The map equals the territory, so to speak 🙂.
extension MainViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let capitalAnnotation = annotation as? CapitalAnnotation else {
return nil
}
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationReuseIdentifier) {
annotationView.annotation = capitalAnnotation
return annotationView
} else {
return makeNewCapitalAnnotationView(capitalAnnotation)
}
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if let capitalAnnotation = view.annotation as? CapitalAnnotation {
showDetailModal(forAnnotation: capitalAnnotation)
}
}
func makeNewCapitalAnnotationView(_ capitalAnnotation: CapitalAnnotation) -> MKPinAnnotationView {
let annotationView = MKPinAnnotationView(annotation: capitalAnnotation, reuseIdentifier: self.annotationReuseIdentifier)
let button = UIButton(type: .detailDisclosure)
annotationView.canShowCallout = true
annotationView.rightCalloutAccessoryView = button
return annotationView
}
func showDetailModal(forAnnotation annotation: CapitalAnnotation) {
let alertController = UIAlertController(title: annotation.title, message: annotation.shortDescription, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true)
}
}