代码之家  ›  专栏  ›  技术社区  ›  noizybrain

防止在MKMapView中取消选择注释

  •  1
  • noizybrain  · 技术社区  · 9 年前

    我的应用程序中有一种情况,我想禁用注释取消选择(而不是选择其他注释时),所以当我点击任何地方 一个注释视图,它应该保持当前选定的注释不变。如果我点击另一个注释,它应该选择一个并取消选择另一个。

    我希望能找到一些类似 willDeselectAnnotationView MKMapViewDelegate isDeselected 在里面 MKAnnotationView ,但不幸的是没有这样的事情。我也试着超越 deselectAnnotation 在的自定义子类中 MKMapView ,但点击触发的取消选择似乎不会调用该函数。

    是否可以在保留选择功能的同时禁用注释取消选择?谢谢

    3 回复  |  直到 9 年前
        1
  •  3
  •   noizybrain    9 年前

    我找到了一种方法!制作一个名为“allowSelectionChanges”的布尔值,我现在只将其作为全局值。然后在MKMapView的子类中使用此重写函数:

    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
            return allowSelectionChanges
        } 
    

    只要您想阻止注释选择和取消选择,请将此变量切换为false。它不会影响用户在地图上移动的能力!


    下面是一个示例,说明当您点击标注进行交互时,如何使用它来阻止标注被取消选中。把这个放在你的 MKAnnotationView 子类:

    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
            let rect = self.bounds
            var isInside = CGRectContainsPoint(rect, point)
            if !isInside {
                for view in self.subviews {
                    isInside = CGRectContainsPoint(view.frame, point)
                    if isInside {
                        allowSelectionChanges = false
                        return true
                    }
                }
                allowSelectionChanges = true
            }
    
            return false
        }
    
        2
  •  0
  •   Mihai Fratu    7 年前

    好吧……我自己也有这个问题,虽然@clinton的回答给我指明了正确的方向,但我想出了一个解决方案,不需要你 MKAnnotationView 要了解的子类 mapView 的自定义属性。

    这是我为Swift 3编写的解决方案:

    public class <#CustomMapViewClass#>: MKMapView {
    
        private var allowSelectionChanges: Bool = true
    
        public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return allowSelectionChanges
        }
    
        public override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            let pointInside = super.point(inside: point, with: event)
            if !pointInside {
                return pointInside
            }
    
            for annotation in annotations(in: visibleMapRect) where annotation is <#CustomAnnotationViewClass#> {
                guard let view = self.view(for: annotation as! MKAnnotation) else {
                    continue
                }
                if view.frame.contains(point) {
                    allowSelectionChanges = true
                    return true
                }
            }
            allowSelectionChanges = false
    
            return pointInside
        }
    
    }
    
        3
  •  0
  •   Erik Allen    5 年前

    我的工作基于@clinton和@mihai fratu。他们都给出了很好的答案,所以你也应该投他们一票。我想补充的是,如果点击的注释在一个集群中,或者如果它被禁用,那么您仍然可以取消选择。这是我试图修复的代码。

    public class <#CustomMapViewClass#>: MKMapView {
    
        private var allowSelectionChanges: Bool = true
    
        public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return allowSelectionChanges
        }
    
        public override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            let pointInside = super.point(inside: point, with: event)
            if pointInside {
                // Go through all annotations in the visible map rect
                for annotation in annotations(in: visibleMapRect) where annotation is MKAnnotation {
                    // get the view of each annotation
                    if let view: MKAnnotationView = self.view(for: annotation as! MKAnnotation) {
                        // work with the cluster view if there is one
                        let rootView = view.cluster ?? view
                        // If the frame of this view contains the selected point, then we are an annotation tap. Allow the gesture...
                        if (rootView.frame.contains(point)) {
                            allowSelectionChanges = rootView.isEnabled  // But only if the view is enabled
                            return pointInside
                        }
                    }
                }
                // If you did not tap in any valid annotation, disallow the gesture
                allowSelectionChanges = false
            }
            return pointInside
        }
    }