【问题标题】:Display overlay view when selecting annotation in SwiftUI在 SwiftUI 中选择注释时显示覆盖视图
【发布时间】:2021-11-02 21:36:17
【问题描述】:

我正在使用 UIRepresentable 在地图上显示注释,并且希望能够在点击所选图钉时显示视图。

我之前使用Map(),所以可以使用.onTapGesture作为注释,但是现在注释是由UIKit制作的,我如何将选定的项目传递给主视图?

我之前的工作:

var body: some View {
  ZStack {
    Map(region: $region, annotationItems: $model.locations) { location in
      MapPin(coordinate: location.coord)
        .onTapGesture {
          modelData.selectedLocation = location
          modelData.isShowingDetail = true
        }
    }
    if modelData.isShowingDetail {
      DetailView(
        isShowingDetail: $modelData.isShowingDetail,
        location: modelData.selectedLocation!
      )
    }
  }
}

现在我有了 UIViewRepresentable:

struct UIMapView: UIViewRepresentable {

  // default setup - coordinator, makeUI, updateUI

  class Coordinator: NSObject, MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
      // how to trigger the overlay??
    }
  }
}

任何帮助将不胜感激,因为我非常坚持这一点:)

【问题讨论】:

    标签: swift swiftui mapkit mapkitannotation


    【解决方案1】:

    您想知道您的 SwiftUI 视图中选择的注解。所以你必须把它存储在某个地方。声明一个@State

    struct ContentView: View {
        let locations: [MKAnnotation]
        @State private var selectedLocation: MKAnnotation?
        var body: some View {
                // ... //
        }
    }
    

    现在在您的包装器 (UIViewRepresentable) 中,您必须使用此 MKAnnotation? 进行绑定:

    struct MapView: UIViewRepresentable {
        @Binding var selectedLocation: MKAnnotation?    // HERE
        let annotations: [MKAnnotation]
    
        func makeUIView(context: Context) -> MKMapView {
            let mapView = MKMapView()
            mapView.region = // .... //
            mapView.addAnnotations(annotations)
            mapView.delegate = context.coordinator
            return mapView
        }
    
        func updateUIView(_ view: MKMapView, context: Context) {
            // .... //
        }
    

    现在您应该能够在您的委托(协调员)中访问此变量。为此,您必须将 UIViewRepresentable 传递给 Coordinator:

        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        class Coordinator: NSObject, MKMapViewDelegate {
            var parent: MapView
    
            init(_ parent: MapView) {
                self.parent = parent
            }
    

    最后在func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) 中,您可以复制parent.selectedLocation 中的MKAnnotation。 使用@Binding,这个MKAnnotation 现在可以在您的父视图(ContentView) 中访问。您可以在DetailView 中显示其属性。

            func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
                // ... //
            }
            
            func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
                parent.selectedLocation = view.annotation
            }
        }
    }
    

    例如:

    struct ContentView: View {
        let locations: [MKAnnotation]
        @State private var selectedLocation: MKAnnotation?
        var body: some View {
            VStack {
                Text("\(selectedLocation?.coordinate.latitude ?? 0)")
    
                // Don't forget the Binding : $selectedLocation
    
                MapView(selectedLocation: $selectedLocation, annotations: locations)
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      在您的class Coordinator: NSObject, MKMapViewDelegate {...} 中,您可以访问以下功能:

       func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
       ...
       }
      
      
      func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { 
      ...
      }
          
      

      使用这些(以及其他)来做你想做的事情。

      【讨论】:

        猜你喜欢
        • 2023-03-03
        • 2021-10-19
        • 2021-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多