SwiftUI中UIViewRepresentable封装的MKMapView添加点击手势无法获取坐标
问题根因
坐标返回nil的核心原因是Coordinator中错误创建了独立的MapView实例:
- 你在Coordinator中定义的
let parent = MapView()是全新的、未渲染的空实例,和实际在界面上加载的MapView没有关联,它的myMapView属性永远为nil - 额外通过
@State持有MKMapView实例的逻辑完全多余,手势识别器可以直接获取到触发事件的地图实例
修正后的完整MapView代码
struct MapView: UIViewRepresentable { typealias UIViewType = MKMapView class Coordinator: NSObject, MKMapViewDelegate { let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194) func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) { if let annotationView = views.first, let annotation = annotationView.annotation, annotation is MKUserLocation { let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000) mapView.setRegion(region, animated: true) } } @objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) { guard sender.state == .ended, let mapView = sender.view as? MKMapView else { return } print("in addAnnotationOnTapGesture") let point = sender.location(in: mapView) print("point is \(point)") let coordinate = mapView.convert(point, toCoordinateFrom: mapView) print("coordinate.latitude is \(coordinate.latitude)") let annotation = MKPointAnnotation() annotation.coordinate = coordinate annotation.title = "Start" mapView.addAnnotation(annotation) } } func makeUIView(context: Context) -> MKMapView { let map = MKMapView() map.showsUserLocation = true map.delegate = context.coordinator let gRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.addAnnotationOnTapGesture(sender:))) map.addGestureRecognizer(gRecognizer) return map } func makeCoordinator() -> Coordinator { Coordinator() } func updateUIView(_ uiView: MKMapView, context: Context) { } }
修改点说明
- 移除了多余的
@State private var myMapView: MKMapView?属性和对应的异步赋值逻辑 - 删除了Coordinator中无意义的
control属性和新建的parent实例 - 点击手势触发时直接通过
sender.view获取当前点击的MKMapView实例,不需要额外持有引用 - 去掉了不必要的可选值绑定,获取到的mapView实例一定不为空,坐标转换不会再返回nil
内容的提问来源于stack exchange,提问作者JohnSF
相关产品推荐
相关产品推荐

