问题
Attempting to show custom point annotations from MapKits local search. When the annotations first load on the map all of them show, but then the overlapping ones disappear. And they only reappear when you zoom in on the area.
Many stack solutions have stated to user view?.displayPriority = .required
. But for some reason this line of code doesn't work.
Local Search Function on button press
@IBAction func groceryLocalSearch(_ sender: Any) {
self.localStoresArray.removeAll()
self.LocalMapKit.removeAnnotations(self.LocalMapKit.annotations)
currentLocationBtn.isHidden = false
localRequest.naturalLanguageQuery = "Grocery"
//localRequest.region = LocalMapKit.region
self.localSearchBtn.isEnabled = false
let search = MKLocalSearch(request: localRequest)
search.start(completionHandler: {(response, error) in
if error != nil{
print("Error occured when searching: \(error!.localizedDescription)")
} else if response!.mapItems.count == 0 {
print("There were no results in the search")
} else {
print("\(response!.mapItems.count) Results found!")
for item in response!.mapItems {
//Add each item to a array to access in table view
self.localStoresArray.append(item)
let stores = MKPointAnnotation()
stores.title = item.name
stores.coordinate = item.placemark.coordinate
self.LocalMapKit.addAnnotation(stores)
}
}
self.LocalMapKit.showAnnotations(self.LocalMapKit.annotations, animated: true)
self.localStoresTableView.reloadData()
})
View for annotation func
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
guard annotation is MKPointAnnotation else { return nil }
let identifier = "Annotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.displayPriority = .required
//annotationView?.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
return annotationView
}
I want it so that when the user does the local search it shows all annotations not matter if they are close to each other without having to zoom in.
Image of current map view:
回答1:
You apparently haven’t set the delegate
for your map view because those annotation views are not MKPinAnnotationView
, but rather the default MKMarkerAnnotationView
. If you’re going to implement MKMapViewDelegate
methods, you have to set the delegate
of the map view (either in IB or programmatically).
This disappearing act is because the default MKMarkerAnnotationView
is configured to enable clustering but you haven’t registered a MKMapViewDefaultClusterAnnotationViewReuseIdentifier
.
So, if you really want pin annotation views and you don’t want clustering, set your map view’s delegate
and your method should accomplish what you want.
I’d personally suggest you reduce view controller bloat by moving the configuration of your annotation view into a MKPinAnnotationView
subclass:
class CustomAnnotationView: MKPinAnnotationView { // or use `MKMarkerAnnotationView` if you want
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
displayPriority = .required
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Then, if you’re targeting iOS 11 and later, in your viewDidLoad
, you can register your class, and you don’t have to implement mapView(_:viewFor:)
at all:
mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
Or, if you want to enjoy clustering properly, you can expand your CustomAnnotationView
:
class CustomAnnotationView: MKPinAnnotationView { // or use `MKMarkerAnnotationView` if you want
static let preferredClusteringIdentifier: String? = Bundle.main.bundleIdentifier! + ".CustomAnnotationView"
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
clusteringIdentifier = CustomAnnotationView.preferredClusteringIdentifier
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var annotation: MKAnnotation? {
didSet {
clusteringIdentifier = CustomAnnotationView.preferredClusteringIdentifier
}
}
}
And then register both your annotation view and a cluster annotation view:
mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)
Then you enjoy clustering with minimal effort.
来源:https://stackoverflow.com/questions/55819699/how-to-fix-custom-point-annotations-from-disappearing-from-overlap