M6L10 : Delegates

I’ve seen a little about “delegates” when viewing code before, but it didn’t make sense. Lesson 10 of Module 6 from CodeWithChris takes us into UIKit, which is required for the MapView elements.

I had to keep rewinding Chris’ video tutorial, but I don’t think much of it sank in after several goes. No wonder Apple came up with SwiftUI if UIKit is so complicated/convoluted.

In the end, I just proceded with the lesson, following along with Chris’ coding, in the hope that, at some point, some of it will sink in.

This is the essence of today’s code:

import SwiftUI
import MapKit

struct BusinessMap: UIViewRepresentable {
    
    ...

    func makeCoordinator() -> Coordinator {
        return Coordinator()
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            if annotation is MKUserLocation {
                return nil
            }
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: Constants.annotationReuseId)
            if annotationView == nil {
                annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: Constants.annotationReuseId)
                annotationView!.canShowCallout = true
                annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
            }
            else {
                annotationView!.annotation =  annotation
            }
            return annotationView
        }
    }
}

I don’t pretend to be able to summarise what most of that does right now. This crash course in using UIKit is having an even tougher time in my head than SwiftUI is.

However, for the most part, this empowers the red “map pins” that we see on the map view. If we click on the map pin, we get a pop-up annotation showing the text related to the pin.

annotationView!.canShowCallout = true

We also have a clickable information icon / button which will ultimately display more information (when we get to that lesson).

annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

Each annotation is asigned a string ID that we’ve set up in our Constants file. This enables the system to reuse IDs that are no longer useful (such as when pins are scrolled “off screen”) and assign them elsewhere (such as when new pins scroll into view). This helps save memory.

annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: Constants.annotationReuseId)

By default, the user’s location (the blue dot) is not shown because there’s no annotation (I think that’s the reason). In order to show it, we check for it and then don’t try to apply annotations to it:

if annotation is MKUserLocation {
    return nil
}

I think I’ll be revisiting this fairly frequently until I can get my head around it all.