Skip to content

Latest commit

 

History

History

day-060

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Day 60: Project 16: Capital Cities, Part One

Follow along at https://www.hackingwithswift.com/100/60.

📒 Field Notes

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

Up and Running with MapKit

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)

Annotations and Accessory Views: MKPinAnnotationView

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

🔗 Additional/Related Links