如何检测MKMapView上的点击事件但忽略MKAnnotationView上的点击
解决MKMapView点击大头针时同时触发添加新大头针的问题
你的问题核心在于UITapGestureRecognizer会响应MapView及其所有子视图的点击事件,包括你自定义的MKAnnotationView。要让手势只识别MapView本身的点击,有两种常用的解决思路,我给你详细拆解:
方法一:利用手势识别器的代理过滤事件
这是最优雅的处理方式,通过UIGestureRecognizerDelegate的方法拦截不需要的手势事件:
- 先让你的视图控制器遵循
UIGestureRecognizerDelegate协议:
class YourViewController: UIViewController, UIGestureRecognizerDelegate { // ... 你的现有代码 }
- 给你的UITapGestureRecognizer设置代理:
// 假设你是这样创建手势的(如果已经创建,直接补充代理设置即可) let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:))) tapGesture.delegate = self parent.mapView.addGestureRecognizer(tapGesture)
- 实现代理方法,判断触摸的视图是否为MKAnnotationView(或其子视图),如果是就拒绝让手势处理该事件:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { let touchedView = touch.view // 检查触摸目标是否是大头针视图或其子视图 if touchedView is MKAnnotationView || touchedView?.superview is MKAnnotationView { return false } return true }
这样点击大头针时,手势会直接跳过,不会执行tapHandler里的添加逻辑。
方法二:在tapHandler里直接判断点击位置是否有大头针
如果你不想用代理,也可以在触发手势时先检查点击位置是否存在大头针,再决定是否执行添加操作:
修改你的tapHandler方法:
@objc func tapHandler(_ gesture: UITapGestureRecognizer) { let location = gesture.location(in: parent.mapView) // 检查该位置是否存在大头针 let tappedAnnotations = parent.mapView.annotations(at: location) if !tappedAnnotations.isEmpty { // 点击到了大头针,直接返回不执行添加逻辑 return } // 未点击到大头针,继续执行添加流程 let coordinate = parent.mapView.convert(location, toCoordinateFrom: parent.mapView) parent.shapeCoordinates.append(coordinate) self.redrawTheMap() }
这个方法利用MapView的annotations(at:)方法获取点击位置对应的所有大头针,若结果不为空则说明点击到了大头针,直接终止添加操作。
额外提示
两种方法都能解决你的问题,个人更推荐第一种代理方案——逻辑更清晰,也更符合iOS的事件处理机制。另外记得确保mapView(_:didSelect:)的删除逻辑不受影响,目前你的这段代码是没问题的。
内容的提问来源于stack exchange,提问作者paulopadopalos
相关产品推荐
相关产品推荐

