简体   繁体   English

无法将 Tap Gesture Recognizer 添加到 SwiftUI MKMapView UIViewRepresentable

[英]Can't add Tap Gesture Recognizer to SwiftUI MKMapView UIViewRepresentable

I have a SwiftUI app with SwiftUI life cycle and I'm trying to get a tap gesture to work in an MKMapView.我有一个生命周期为 SwiftUI 的应用程序,它的生命周期为 SwiftUI,我正在尝试让点击手势在 MKMapView 中工作。 I can't seem to get the reference to the map correctly.我似乎无法正确获得对 map 的引用。 All I want to do in this subsection is tap the map and add an annotation.在本小节中,我只想点击 map 并添加注释。 I would then also use the coordinates of the annotation.然后我也会使用注释的坐标。

Here's the code.这是代码。

struct MapView: UIViewRepresentable {

    typealias UIViewType = MKMapView
    @State private var myMapView: MKMapView?

    class Coordinator: NSObject, MKMapViewDelegate {
        var control: MapView
        let parent = MapView()
    
        let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)

        init(_ control: MapView) {
            self.control = control
        }
    
        func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
            if let annotationView = views.first {
                if let annotation = annotationView.annotation {
                    if annotation is MKUserLocation {
                        let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
                        mapView.setRegion(region, animated: true)
                    }
                }
            }
        }//did add
    
        @objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
            if sender.state == .ended {
                print("in addAnnotationOnTapGesture")
                let point = sender.location(in: parent.myMapView)
                print("point is \(point)")
                let coordinate = parent.myMapView?.convert(point, toCoordinateFrom: parent.myMapView)
                print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
                let annotation = MKPointAnnotation()
                annotation.coordinate = coordinate ?? sfCoord
                annotation.title = "Start"
                parent.myMapView?.addAnnotation(annotation)
            }
        }
    }//coord

    func makeUIView(context: Context) -> MKMapView {
        let map = MKMapView()
        map.showsUserLocation = true
        map.delegate = context.coordinator
    
        DispatchQueue.main.async {
            self.myMapView = map
        }
    
        let gRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.addAnnotationOnTapGesture(sender:)))
        map.addGestureRecognizer(gRecognizer)

        return map
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {

    }
}//struct MapView

And the LocationManager for reference:和 LocationManager 供参考:

class LocationManager: NSObject, ObservableObject {
    private let locationManager = CLLocationManager()
    @Published var location: CLLocation? = nil

    override init() {
        super.init()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.distanceFilter = kCLDistanceFilterNone
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
    }
}

extension LocationManager: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        print(status)
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
    
        self.location = location
    }
}//extension

And finally the ContentView:最后是内容视图:

struct ContentView: View {

    @ObservedObject var locationManager = LocationManager()

    var body: some View {
        MapView()
    }
}

Tapping the map shows a console output like this:点击 map 会显示一个控制台 output,如下所示:

in addAnnotationOnTapGesture在添加AnnotationOnTapGesture

point is (156.0, 515.6666564941406)点是 (156.0, 515.6666564941406)

coordinate?.latitude is nil坐标?.纬度为零

Any guidance would be appreciated.任何指导将不胜感激。 Xcode 12.5 iOS 14.5 Xcode 12.5 iOS 14.5

In your Coordinator , you have two references to MapView s.在您的Coordinator中,您有两个对MapView的引用。 One ( control ) is set in init and represents the actual view that you want.一个( control )在init中设置并代表您想要的实际视图。 The other ( parent ) is defined within your Coordinator and is not actually part of the view hierarchy.另一个( parent )在您的Coordinator中定义,实际上并不是视图层次结构的一部分。 Therefore, when you try to get a coordinate from it, it returns nil .因此,当您尝试从中获取坐标时,它会返回nil You can change all of the references to control and it works:您可以将所有引用更改为control并且它有效:

class Coordinator: NSObject, MKMapViewDelegate {
    var control: MapView

    let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)

    init(_ control: MapView) {
        self.control = control
    }

    func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
        if let annotationView = views.first {
            if let annotation = annotationView.annotation {
                if annotation is MKUserLocation {
                    let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
                    mapView.setRegion(region, animated: true)
                }
            }
        }
    }//did add

    @objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
        if sender.state == .ended {
            print("in addAnnotationOnTapGesture")
            let point = sender.location(in: control.myMapView)
            print("point is \(point)")
            let coordinate = control.myMapView?.convert(point, toCoordinateFrom: control.myMapView)
            print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
            let annotation = MKPointAnnotation()
            annotation.coordinate = coordinate ?? sfCoord
            annotation.title = "Start"
            control.myMapView?.addAnnotation(annotation)
        }
    }
}//coord

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM