struct DetailMapView: UIViewRepresentable { let kAppDelegate = UIApplication.shared.delegate as! AppDelegate @Environment(\.presentationMode) var presentationMode @ObservedObject var mdm: MyDefaultsManager @State var insertSequence : Int = 0 @State var annotations: [MKAnnotation] = [] @State var s: Int64 = 0 @State var directionsArray: [MKDirections] = [] var aTrip: Trip? @Binding var thumbImage: UIImage class Coordinator: NSObject, MKMapViewDelegate { var parent: DetailMapView init(_ parent: DetailMapView) { self.parent = parent parent.mdm.tripTimeAndDistance = "Waiting for servers..." } func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) { parent.mdm.pubCenterCoordinate = mapView.centerCoordinate } func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { //unrelated code that always works return crsAnnotationView }//viewfor func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { //print("hello - annotation view tapped") } func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { //unrelated code that always works }//annotationView func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline) renderer.strokeColor = UIColor.blue renderer.lineWidth = 4.0 return renderer }//rendererFor }//class coordinator func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> MKMapView { DispatchQueue.main.async { self.mdm.totalRouteDistance = 0.0 self.mdm.totalTravelTime = 0.0 self.mdm.callbackDistance = 0.0 self.mdm.callbackTime = 0.0 } self.mdm.showAddWaypointControls = false let mapView = MKMapView() mapView.showsUserLocation = true mapView.delegate = context.coordinator mdm.tripTimeAndDistance = "Calculating..." redrawTheMap2(trip: aTrip, mapView: mapView, callback2: callback2DistanceAndTime) return mapView } func updateUIView(_ view: MKMapView, context: Context) { //no code here }//updateUIView func doOneWaypointPolylineCallback2(view: MKMapView, source: CLLocationCoordinate2D, destination: CLLocationCoordinate2D, callback: @escaping (Double, Double) -> Void) { var totDist = 0.0 var totTrav = 0.0 for anotation in annotations { view.deselectAnnotation(anotation, animated: false) } view.removeAnnotations(annotations) let request = MKDirections.Request() request.source = MKMapItem(placemark: MKPlacemark(coordinate: source)) request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destination)) request.requestsAlternateRoutes = false request.transportType = mdm.walkDirections ? .walking : .automobile let directions = MKDirections(request: request) directions.calculate { response, error in guard let unwrappedResponse = response else { if let error = error { print("Direction calulation failed: \(error.localizedDescription)") self.mdm.tripTimeAndDistance = "The servers could not be reached. Please try later." //throw an alert here to tell the user } return }//guard let route = unwrappedResponse.routes[0] view.addOverlay(route.polyline) totTrav += route.expectedTravelTime totDist += route.distance self.mdm.totalRouteDistance += totDist self.mdm.totalTravelTime += totTrav callback(self.mdm.totalRouteDistance, self.mdm.totalTravelTime) } }//doOneWaypoint Polyline Callback2 func resetMapView(mapView: MKMapView, withNew directions: MKDirections) { mapView.removeOverlays(mapView.overlays) DispatchQueue.main.async { self.directionsArray.append(directions) let _ = self.directionsArray.map { $0.cancel() } self.directionsArray.removeAll() } } func chooseTransportType() -> MKDirectionsTransportType { //unrelated code that always works }//chooseTransportType func updateDistanceAndTimeTupleSingle(distance : Double, time : Double) { self.mdm.callbackDistance += distance self.mdm.callbackTime += time let totalDistance = NU.formatDistance(distanceMeters: distance, isMetric: self.mdm.metricDistance) let totalTime = NU.formatTime(timeInSec: time) self.mdm.tripTimeAndDistance = "Combined distance is " + totalDistance + " and combined travel time is " + totalTime + "\n" }//update DistanceAndTime Tuple func redrawTheMap2(trip: Trip?, mapView: MKMapView, callback2: @escaping (Double, Double) -> Void) { mdm.redrawTheMap2Count += 1 print("udm.redrawTheMap2Count is \(mdm.redrawTheMap2Count)") mapView.removeAnnotations(mapView.annotations) mapView.removeOverlays(mapView.overlays) guard let detail = aTrip else { return } for waypoint in detail.waypoints { let wp = waypoint as! Waypoint //print("waypoint sequence number = \(wp.sequence)") let coordinate = CLLocationCoordinate2D(latitude: (waypoint as! Waypoint).latitude, longitude: (waypoint as! Waypoint).longitude) //make an annotation from the waypoint information let annotation = AnnotationPin(wp: wp, title: "WP" + String(wp.sequence), subtitle: wp.name ?? "Subtitle", coordinate: coordinate) //this is the only place annotations are added to the detail view mapView.addAnnotation(annotation) }//for in let wpArray = Array(detail.waypoints).sorted(by: { ($0 as AnyObject).sequence < ($1 as AnyObject).sequence }) var wpSourceSequence = 0 var wpDestinationSequence = 1 //for callback 2 self.mdm.callbackDistance = 0.0 self.mdm.callbackTime = 0.0 //callback 2 above while wpDestinationSequence < wpArray.count { doOneWaypointPolylineCallback2(view: mapView, source: CLLocationCoordinate2D(latitude: (wpArray[wpSourceSequence] as! Waypoint).latitude, longitude: (wpArray[wpSourceSequence] as! Waypoint).longitude), destination: CLLocationCoordinate2D(latitude: (wpArray[wpDestinationSequence] as! Waypoint).latitude, longitude: (wpArray[wpDestinationSequence] as! Waypoint).longitude), callback: updateDistanceAndTimeTupleSingle) wpSourceSequence += 1 wpDestinationSequence += 1 }//while callback2(self.mdm.callbackDistance, self.mdm.callbackTime) }//redraw The Map 2 func callback2DistanceAndTime (distance : Double, time : Double) { print("TryYo \(distance) and TryYo \(time)") } }