I would like to toggle the visibility of the title of my MKPointAnnotation after I tap the pin. I tried changing the title directly in
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView)
but it tells me that it's only a get property and I cannot change it inside of my Coordinator class.
Any help would be much appreciated!
Here is the relevant code...
import SwiftUI
import MapKit
import CoreLocationUI
struct MapViewTest: UIViewRepresentable {
@EnvironmentObject var viewModel: MapViewModel
@Binding var region: MKCoordinateRegion
@Binding var lineCoordinates: [[CLLocationCoordinate2D]]
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
mapView.region = region
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
view.setRegion(region, animated: true)
for i in viewModel.locations {
let pin = MKPointAnnotation()
pin.coordinate = i.coordinate
pin.title = i.name
view.addAnnotation(pin)
}
for i in lineCoordinates{
let polyline = MKPolyline(coordinates: i, count: i.count)
view.addOverlay(polyline)
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapViewTest
init(_ parent: MapViewTest) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let routePolyline = overlay as? MKPolyline {
let renderer = MKPolylineRenderer(polyline: routePolyline)
renderer.strokeColor = UIColor.systemBlue
renderer.lineWidth = 10
return renderer
}
return MKOverlayRenderer()
}
}
Whenever you are making a MapKit annotation, you should include func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
. This function allows you to configure your pins, but it also allows you to reuse unused pins. Whenever a pin disappears from a map (scrolling around, etc.), that pin is not destroyed, but it is held to be reused in another pin is needed. This saves processor and memory.
In your Coordinator
class add the following function:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// create a unique identifier for pin reuse
let identifier = "Placemark"
// see if there already is a created pin
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
// there wasn't a pin, so we make a new one
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
// this is where your title is allowed to be shown when tapping the pin
annotationView?.canShowCallout = true
// this gives you an information button in the callout if needed
// if you use the rightCalloutAccessoryView you must implement:
// func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
} else {
// we have an old annotation, so update it
annotationView?.annotation = annotation
}
return annotationView
}