SwiftUI中UIViewRepresentable地图的标注与地图点击事件冲突问题
解决SwiftUI集成MKMapView时标注点击触发地图Tap手势的问题
问题核心是点击标注时,自定义的UITapGestureRecognizer会和地图自身的标注选择事件同时触发,我们需要通过手势代理区分点击目标,避免手势响应标注区域的点击。
解决方案
在你的MapCoordinator类中实现UIGestureRecognizerDelegate的gestureRecognizer(_:shouldReceive:)方法,判断点击位置是否属于标注视图,若是则阻止手势响应:
final class MapCoordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate { var parent: UIkitMapView var gRecognizer = UITapGestureRecognizer() init(_ parent: UIkitMapView) { self.parent = parent super.init() self.gRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler)) self.gRecognizer.delegate = self self.parent.mapView.addGestureRecognizer(gRecognizer) } // 新增:阻止手势响应标注视图的点击 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let hitView = touch.view, hitView is MKAnnotationView { return false } return true } func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { print(view.annotation?.title) parent.showPlaceDetails = true } @objc func tapHandler(_ gesture: UITapGestureRecognizer) { let location = gRecognizer.location(in: self.parent.mapView) let coordinate = self.parent.mapView.convert(location, toCoordinateFrom: self.parent.mapView) let pin = MKPointAnnotation() pin.coordinate = coordinate parent.setPinOnMap(point: pin) print("new pin") } }
原理说明
- 当触摸事件触发时,
gestureRecognizer(_:shouldReceive:)会先被调用,我们通过touch.view获取触摸点对应的视图。 - 如果该视图是
MKAnnotationView(即标注视图),返回false,表示不让自定义的Tap手势处理这个事件。 - 此时只有地图的
didSelect MKAnnotationView代理方法会响应标注点击,而地图空白区域的点击仍会触发tapHandler添加新标注。
内容的提问来源于stack exchange,提问作者Anton Nikitin
相关产品推荐
相关产品推荐

