UILongPressGestureRecognizer在MapKit(适配器)中失效问题排查
MapKit适配器中长按手势失效问题
我通过适配器对象在视图控制器中使用MapKit,给大头针视图(PinView)同时添加了长按和点击手势,但仅长按手势无法触发,点击手势正常工作。相关代码如下:
手势准备代码
private func prepareGestures(on pinView: PinViewProtocol) { let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:))) longPressGesture.delegate = self longPressGesture.minimumPressDuration = Constants.longPressDuration let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:))) tapGesture.delegate = self pinView.addGestureRecognizers([tapGesture, longPressGesture]) }
手势添加逻辑
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard let annotation = annotation as? MyPinAnnotation else { return nil } prepareGestures(on: pinView) return pinView }
适配器配置代码
private func configureMapView() { mapViewAdapter = TestMapViewAdapter(mapView: mapView) }
解决方案
1. 处理手势识别冲突
点击手势的响应优先级高于长按,会提前拦截触摸事件导致长按无法触发。通过手势代理调整识别规则:
extension TestMapViewAdapter: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { // 允许长按与点击手势同时识别 return gestureRecognizer is UILongPressGestureRecognizer && otherGestureRecognizer is UITapGestureRecognizer } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { // 让点击手势等待长按手势失败后再触发 return gestureRecognizer is UITapGestureRecognizer && otherGestureRecognizer is UILongPressGestureRecognizer } }
2. 移除MapKit默认长按手势干扰
MKMapView自带长按手势用于添加系统大头针,会和自定义手势冲突。在适配器初始化时移除系统手势:
init(mapView: MKMapView) { self.mapView = mapView // 移除系统默认长按手势 mapView.gestureRecognizers?.removeAll(where: { $0 is UILongPressGestureRecognizer }) }
3. 确保视图交互开启
确认PinViewProtocol对应的视图类已开启用户交互(虽然点击生效大概率已开启,但需验证):
class PinView: MKAnnotationView, PinViewProtocol { override init(annotation: MKAnnotation?, reuseIdentifier: String?) { super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) self.isUserInteractionEnabled = true } }
4. 修正手势添加时机
避免在视图复用时重复添加手势,仅在首次创建视图时添加:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard let annotation = annotation as? MyPinAnnotation else { return nil } let reuseId = "MyPinAnnotation" var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? PinViewProtocol if pinView == nil { pinView = PinView(annotation: annotation, reuseIdentifier: reuseId) prepareGestures(on: pinView!) } pinView?.annotation = annotation return pinView as? MKAnnotationView }
内容的提问来源于stack exchange,提问作者Kaan Vural
相关产品推荐
相关产品推荐

