I have a SwiftUI app where a couple of views are MapKit maps made with UIViewRepresentable. I have custom annotations for the points of interest and use both the right and left callout buttons for further action. On the right I simply want to display information about the waypoint. On the left I want to raise an alert with a choice of further actions - for example, insert a new annotation point. Before SwiftUI I just raised an alert and did both of the above. But from what I can tell, there is no self.present on the UIViewRepresentable versions. Hence I have not been able to present alerts.
Just for an experiment - I attached SwiftUI alert code to the SwiftUI view that calls the MapView. Using Observable booleans I can indeed raise both those alerts. That seems strange to me but maybe the code for alerts bound to global properties can be ANYWHERE.
My first attempt: (the struct is DetailMapView)
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.leftCalloutAccessoryView {
guard let tappedLocationCoord = view.annotation?.coordinate else {return}
let tappedLocation = CLLocation(latitude: tappedLocationCoord.latitude, longitude: tappedLocationCoord.longitude)
let ac = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
let deleteAction = UIAlertAction(title: "Delete Waypoint", style: .destructive) { (action) in
//some stuff
}
let insertAction = UIAlertAction(title: "Insert Waypoint After This", style: .default) { (action) in
//some stuff
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default) { (action) in
//some stuff
}//cancelAction
ac.addAction(deleteAction)
ac.addAction(insertAction)
ac.addAction(cancelAction)
//tried adding self, referencing parent - always error saying
//the object does not have a .present
mapView.present(ac, animated: true)
} else if control == view.rightCalloutAccessoryView {
//more of the same
}
}//annotationView
I then removed the alert code and added:
parent.userDefaultsManager.shouldShowAnnotationEditMenu.toggle()
And I changed the calling screen to:
@ObservedObject var userDefaultsManager: UserDefaultsManager
var aTrip: Trip?
var body: some View {
VStack {
Text(aTrip?.name ?? "Unknown Map Name")
.padding(.top, -50)
.padding(.bottom, -20)
DetailMapView(aTrip: aTrip, userDefaultsManager: userDefaultsManager)
.padding(.top, -20)
.alert(isPresented: $userDefaultsManager.shouldShowAddress) {
//Alert(title: Text("\(aTrip?.name ?? "No") Address"),
Alert(title: Text(self.userDefaultsManager.approximateAddress),
message: Text("This is the approximate street address."),
dismissButton: .default(Text("Got it!")))
}//.alert shouldShowAddress
Text("This is the view where the trip information will be displayed.")
.multilineTextAlignment(.center)
.alert(isPresented: $userDefaultsManager.shouldShowAnnotationEditMenu) {
Alert(title: Text("Edit Annotations"),
message: Text("Choose this to insert an Annotation."),
dismissButton: .default(Text("Got it!")))
}//.alert shouldShowAddress
}
}
I guess if this is safe I could make it work - but it seems more complicated that it should be.
This is the idea:
Any guidance would be appreciated: Xcode Version 11.3.1 (11C504)