没有 UIViewRepresentable 的 SwiftUI 地图叠加

Paw*_*dej 4 delegates uikit mapkit swift swiftui

我尝试仅使用 iOS 14 SwiftUI 地图创建带有注释和叠加层的地图视图。我设法创建注释,但由于 MKMapView 委托缺少 MKOverlayRenderer,因此无法创建可见的叠加层。如何附加到地图视图委托以便​​它可以运行其方法

    Map(coordinateRegion: $region, showsUserLocation: true, userTrackingMode: $userTrackingMode, annotationItems: annotations)) { annotation in
        MapAnnotation(coordinate: CLLocationCoordinate2DMake(annotation.latitude, annotation.longitude),
                      anchorPoint: CGPoint(x: 0.5, y: 0.7)) {
            NavigationLink(destination: DetailsView()) {
                VStack {
                    Image(systemName: "mappin")
                        .font(.title)
                        .foregroundColor(.red)
                    Text(annotation.name.split(separator: " ").joined(separator: "\n"))
                        .font(.caption)
                        .bold()
                        .multilineTextAlignment(.center)
                        .foregroundColor(.black)
                        .padding(2)
                        .background(RoundedRectangle(cornerRadius: 4).fill(Color.white.opacity(0.8)))
                        .layoutPriority(1)
                }
            }
        }
    }
    .addOverlays(mapOverlays, delegate: mapDelegate)
Run Code Online (Sandbox Code Playgroud)

和地图扩展方法:

extension Map {
    func addOverlays(_ overlays: [MKOverlay], delegate: MKMapViewDelegate) -> some View {
        // MKMapView.appearance().delegate = delegate // THIS DOES NOT WORK AT ALL

        MKMapView.appearance().addOverlays(overlays)

        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

并委托:

class MapDelegate: NSObject, MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if overlay is MKCircle {
            let circle = MKCircleRenderer(overlay: overlay)
            circle.strokeColor = .systemRed
            circle.fillColor = .systemRed
            circle.alpha = 0.2
            circle.lineWidth = 1

            return circle
        }
        return MKOverlayRenderer()
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

绝对不可能,SwiftUI Map 还不支持叠加。使用 UIViewRepresentsable 很容易,请参见此处的示例:
Swiftui 如何使用 MKOverlayRenderer? 使用以下代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)