M6L11 : UIKit Events

Having assigned the annotations last time around, this time we use them to react to the user tapping on them.

In Lesson 11 of Module 6 from the CodeWithChris iOS Foundations course, we react to the user tapping on the annotation to display details of the business in question.

This introduces us to a new .sheet modifier which we can use to call our BusinessDetail view, passing into it the business selected by the user’s tap.

To this end, we make these changes to the HomeView:

...
@State var selectedBusiness:Business?
...
var body: some View {
    if model.restaurants.count != 0 || model.sights.count != 0 {
        ...
    }
    else { 
        BusinessMap(selectedBusiness: $selectedBusiness)
            .ignoresSafeArea()
            .sheet(item: $selectedBusiness) { business in
                BusinessDetail(business: business)                            
            }
        ...

Being that selectedBusiness is a @State variable, the view is updated when it changes, and so the “sheet” comes into view.

We set-up a two-way binding in the BusinessMap view, thus:

 @Binding var selectedBusiness: Business?

When we call an instance of the Coordinator class, we must pass through the BusinessMap itself so that selectedBusiness is available to the Coordinator() class, re:

func makeCoordinator() -> Coordinator { 
    return Coordinator(map: self)
}

The Coordinator() class can then have access to the business data, thus:

class Coordinator: NSObject, MKMapViewDelegate {
    var map: BusinessMap
    init(map: BusinessMap) { 
        self.map = map
    }
    ...
    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        for business in map.model.restaurants + map.model.sights {
            if business.name == view.annotation?.title { 
                map.selectedBusiness = business
                return
            }
        }
    }
    ...
}

The mapView() method loops though the restaurants and, if a business name is found that matches the one tapped by the user, that bound variable selectedBusiness is set to that business and the loop ends. As this is a @State variable in HomeView, the view is then automatically updated when selectedBusiness changes.

I’m just summarising what I recall from the lesson and what I think is going on here, but it’s going to take a lot of studying of my notes before I’ll have a handle on this.