Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swiftui how to use MKOverlayRenderer?

Tags:

mapkit

swiftui

I want draw a route on the map.

but struct without using delegate.

struct MapView : UIViewRepresentable {
}

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
}

how can I do?

like image 460
trace tw Avatar asked Jan 27 '23 02:01

trace tw


1 Answers

You need to specify a delegate if you want mapView(_:rendererFor:) to be called:

struct MapView: UIViewRepresentable {
    @Binding var route: MKPolyline?
    let mapViewDelegate = MapViewDelegate()

    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }

    func updateUIView(_ view: MKMapView, context: Context) {
        view.delegate = mapViewDelegate                          // (1) This should be set in makeUIView, but it is getting reset to `nil`
        view.translatesAutoresizingMaskIntoConstraints = false   // (2) In the absence of this, we get constraints error on rotation; and again, it seems one should do this in makeUIView, but has to be here
        addRoute(to: view)
    }
}

private extension MapView {
    func addRoute(to view: MKMapView) {
        if !view.overlays.isEmpty {
            view.removeOverlays(view.overlays)
        }

        guard let route = route else { return }
        let mapRect = route.boundingMapRect
        view.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10), animated: true)
        view.addOverlay(route)
    }
}

class MapViewDelegate: NSObject, MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.fillColor = UIColor.red.withAlphaComponent(0.5)
        renderer.strokeColor = UIColor.red.withAlphaComponent(0.8)
        return renderer
    }
}

Used like so:

struct ContentView : View {
    @State var route: MKPolyline?

    var body: some View {
        MapView(route: $route)
            .onAppear {
                self.findCoffee()
        }
    }
}

private extension ContentView {
    func findCoffee() {
        let start = CLLocationCoordinate2D(latitude: 37.332693, longitude: -122.03071)
        let region = MKCoordinateRegion(center: start, latitudinalMeters: 2000, longitudinalMeters: 2000)

        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = "coffee"
        request.region = region

        MKLocalSearch(request: request).start { response, error in
            guard let destination = response?.mapItems.first else { return }

            let request = MKDirections.Request()
            request.source = MKMapItem(placemark: MKPlacemark(coordinate: start))
            request.destination = destination
            MKDirections(request: request).calculate { directionsResponse, _ in
                self.route = directionsResponse?.routes.first?.polyline
            }
        }
    }
}

Yielding:

Coffee

like image 75
Rob Avatar answered Feb 15 '23 15:02

Rob