MapKit Annotations Disappearing

守給你的承諾、 提交于 2019-11-30 20:09:24
Leszek Szary

NiltiakSivad's solution works but it reverts to the old iOS 10 look. If you want to keep the new iOS 11 balloon markers for iOS 11 and use the old pin look only for older iOS versions then you can implement the delegate method as below:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let reuseIdentifier = "annotationView"
    var view = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
    if #available(iOS 11.0, *) {
        if view == nil {
            view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
        view?.displayPriority = .required
    } else {
        if view == nil {
            view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
    }
    view?.annotation = annotation
    view?.canShowCallout = true
    return view
}

I was experiencing a similar issue. My best guess is that it has something to do with how iOS 11 detects pin collisions. Implementing a custom annotation view or reverting to use the iOS 10 pin fixed the problem for me.

For example, implementing the following should fix your code:

class MultiMapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
   override func viewDidLoad() {
       super.viewDidLoad()
       mapView.delegate = self    
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
       guard let annotation = annotation as? MKPointAnnotation else { return nil }

       let identifier = "pin-marker"
       var view: MKAnnotationView

       if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView {
           dequeuedView.annotation = annotation
           view = dequeuedView
       } else {
           view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
       }
       return view
   }
}

If this doesn't work, there is a displayPriority property that is worth looking into as it is responsible for helping to determine when pins should be hidden/shown at different zoom levels. More info at https://developer.apple.com/documentation/mapkit/mkannotationview/2867298-displaypriority

Hope this helps.

The accepted answer from Leszek Szary is correct.

But there is some fineprint. Sometimes MKMarkerAnnotationViews are not rendered, even if

view.displayPriority = .required

is set.

What you are seeing is a combination of different rules.

  1. MKAnnotationViews are rendered from top to bottom of the map. (It doesn't matter where north is).
  2. If MapKit decides to draw overlapping MKAnnotationViews, then the MKAnnotationView nearer to the bottom is drawn on top (because it's drawn later)
  3. Not only MKAnnotationViews, also titles rendered below MKMArkerAnnotationViews need space. The rendering of those titles is influenced by markerView.titleVisibility. If markerView.titleVisibility is set to .visible (instead of the default .adaptive), then this title is stronger than a MarkerAnnotationView that is rendered later, even if the later MarkerAnnotationView has a displayPriority = .required. The MarkerAnnotationView nearer to the bottom is not rendered.
  4. This even happens if the MarkerAnnotationView nearer to the top has a low displayPriority. So a MarkerAnnotationView with low displayPriority and .titleVisibility = .visible can make a MarkerAnnotationView nearer to the bottom with displayPriority = .required disappear.

I am not aware of a documentation of this behaviour. This is the result of my experiments with iOS 12. My description is sipmplified.

I was setting annotationView.displayPriority = .required only when the MKMarkAnnotationView was first allocated. Normally thats all you should need to do, but setting it each time the cell was reused fixed the issue for me.

I was seeing a similar problem with Xcode 10, and iOS 12+ as my deployment target. A post from an Apple staffer (https://forums.developer.apple.com/thread/92839) recommends toggling the .isHidden property on the dequeued marker. That has improved things but has not completely solved the problem.

result?.isHidden = true
result?.isHidden = false
return result
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!