You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 10:54:03