iOS - 添加和删除 MKCircle 覆盖到 MapView 导致故障

Posted

技术标签:

【中文标题】iOS - 添加和删除 MKCircle 覆盖到 MapView 导致故障【英文标题】:iOS -Adding and Removing MKCircle Overlay to MapView causing glitch 【发布时间】:2018-11-03 18:29:17 【问题描述】:

我有一个 MapView,用户可以选择一个半径来显示一个区域。我添加一个 MKCircle 作为覆盖。当半径从 30 英里变为 1 英里时,当 MapView 放大时,MKCircle 的周边会出现明显的故障。故障看起来有点像天赋。只有在放大而不是缩小时才会发生。\

由于缩放不断变化,我在添加另一个覆盖之前删除了旧的覆盖,但我认为这不是问题。

当 MapView 的缩放发生变化时,如何消除圆圈上的故障?

@IBAction func newRadiusButtonTapped(sender: UIButton) 

    // coordinate is the users location and span was 10 miles now it's 1 mile
    let region = MKCoordinateRegionMake(location.coordinate, span)
    mapView.setRegion(region, animated: true)

    let circle = MKCircle(center: location.coordinate, radius: radius)

     // remove old overlay before adding another one
     for overlay in mapView.overlays 
         mapView.remove(overlay)
     

     view.layoutIfNeeded()
     // mapView.layoutIfNeeded() I tried this but it didn't make a difference
     mapView.add(circle)

【问题讨论】:

只是一个问题:你删除所有的覆盖,有必要吗?如果你之前存储过这个圈子,你只需要删除这个特殊的。通过删除 ALL 可能会产生一些副作用......还有一个经典问题:你是在主线程上做的吗? 我一直删除覆盖层的原因是因为当我没有删除它们时,每次按下按钮时都会在覆盖层之上添加覆盖层(mapView.add(circle) 正在添加它们)。我在没有 for 循环的情况下尝试了“mapView.remove(overlay)”,但没有任何效果。我还没有尝试将圆圈存储为类属性。我认为隐藏和取消隐藏它可能会让它看起来很奇怪。这是你的建议吗? 是的,是的,但据我所知,您可以将生成的圆圈存储在类属性中。有了这个参考,你可以删除它:所以有一个类属性“var Circle:MKCircle?”,在你的方法里面:“if circle != nil mapView.remove(Circle)”,并且:而不是“让 circle = MKCircle(..." 使用 "Circle = MKCircle( ..."。这应该可以工作.. @Hardy_Germany 我将它添加为类属性,在按下按钮时对其进行初始化,它没有任何区别。同样的故障。无论如何谢谢:) mmhm 奇怪.. 你试过“func exchangeOverlay(MKOverlay, with: MKOverlay) 交换两个覆盖对象的位置。”有了这个,你可以用新的圆圈交换旧的圆圈......我经常使用这样的覆盖,我从来没有遇到过这样的故障......所以一定有它的原因。 【参考方案1】:

我找不到导致故障的原因,但我在 mapView 上找到了这个委托方法 from this answer,它在 mapView 区域完成更改后得到通知。我在那里添加叠加层

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool)  

简单的过程:

我创建了一个 MKCircle? 类型的 circle 属性 我还创建了 Bool 类型的名为 shouldAddCircle 的属性并将其设置为 true。 当按下按钮时,我使用在按钮内创建的 MKCircle 初始化 circle 属性,并将 shouldAddCircle 设置为 true。 在按钮功能中,我删除了所有 mapViews 覆盖。

在委托方法中,我现在检查 shouldAddCircle 属性是否为 true,如果是,我会检查确保 circle 属性不为 nil。如果它们匹配,那么我将初始化的圆圈添加到 mapView。将圆圈添加到 mapView 后,我必须将 shouldAddCircle 设置为 false,因为每次用户滚动地图时,regionDidChangeAnimated 都会被调用,它会继续向地图添加叠加层。

这里是下面的代码。请务必在viewDidLoad 中添加mapView.delegate = self,并在所有内容之前设置MKMapViewDelegate

var circle: MKCircle?
var shouldAddCircle = true

@IBAction func newRadiusButtonTapped(sender: UIButton) 

    // coordinate is the users location and span was 10 miles now it's 1 mile
    let region = MKCoordinateRegionMake(location.coordinate, span)
    mapView.setRegion(region, animated: true)

    let circle = MKCircle(center: location.coordinate, radius: radius)

    // set the circle property to match the circle that was just created
    self.circle = circle

    // set this true
    shouldAddCircle = true

    // remove old overlay before adding another one
    for overlay in mapView.overlays 
        mapView.remove(overlay)
    


// this function gets called repeatedly as the mapView is zoomed and/or panned
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) 

    // make sure this is true because that means the user updated the radius
    if shouldAddCircle 

       // make sure the circle isn't ni
       if let circle = self.circle 
           // after the mapView finishes add the circle to it
           mapView.add(circle)

           // set this to false so that this doesn't called again until the user presses the button where they set it to true
           shouldAddCircle = false
       
    

【讨论】:

干得好!我只是建议只删除 circleOverlay 而不是所有的覆盖。只是为了避免任何副作用。您可以通过在“let circle = MKCircle ...”语句之前添加“if self.circle != nil mapView.remove(self.circle) 并删除 for 循环以删除所有叠加层来做到这一点。 @Hardy_Germany 好主意,谢谢,这很有意义。非常感谢

以上是关于iOS - 添加和删除 MKCircle 覆盖到 MapView 导致故障的主要内容,如果未能解决你的问题,请参考以下文章

将 MKCircle 半径转换为 ​​CoreGraphics 圆弧半径

使用 UISlider 在 MKMapView 上将半径更改为 MKCircle

如何删除或覆盖添加到 pyspark 作业的文件?

iOS 制作两个视图覆盖全视图

使用由两个远点定义的半径绘制的 MKCircle 渲染不正确

Java - 不要用缓冲写入器覆盖