I am in the middle of developing an application for iOS and have come across an issue with custom annotations on my map view.
Here is the idea:
1) I load in the users location to the map, from this location I send a request to my back end server to retrieve all nearby points of interest.
2) I have a custom annotation as follows:
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String?
var activeImageName : String?
var trainCrossingId : Int?
var notificationCount : UILabel = UILabel()
var labelIsHidden : Bool = true
}
when I add the annotations onto the map, I am dynamically setting the notificationCount
label to use data that I have retrieved from my Firebase Database.
3) A user is able to increase/decrease the size of the radius around their current location. With this new radius selected, I use mapView.removeAnnotations(mapView.annotations)
to remove all annotations and then re-add these annotations with the new data retrieved from the server using the selected radius.
The Issue:
When initially loading the view, the annotations are working as expected with the correct labels set etc.
However, once a user updates the radius and I remove/add the previous annotations, the annotations and their corresponding labels are not showing as expected.
For example, this is what the map looks like when first entering into the view:
And then once I change the size of the radius:
The expected data is what is shown in the initial image (when first entering the view), but when the radius is updated the z-value of my annotations are not respected, and notificationCount
is not correct (eg, the third point found in the second diagram should not have a label). This is weird as I have set up print statements and break points to monitor each annotation in func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {...}
and the values are correct and what I expect, however the view is not displaying these values.
Any ideas as to what might be going wrong here? Thanks in advance!
Edit to include the following mapView delegate:
// Custom annotation view
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "trainPin"
var anView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
}
else {
anView?.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
let icon : UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
icon.image = UIImage(named:cpa.imageName)
icon.layer.zPosition = 1
anView?.rightCalloutAccessoryView = cpa.annotationButton
anView?.addSubview(cpa.notificationCount)
anView?.addSubview(icon)
anView?.frame = CGRect(x: 0, y:0, width:32, height:32)
anView?.canShowCallout = true
return anView
}
I believe that as anView
will be reused, the view will have many subviews as you remove and add annotations. Try to remove the subviews first then add again:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "trainPin"
var anView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
}
else {
anView?.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
let icon : UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
icon.image = UIImage(named:cpa.imageName)
icon.layer.zPosition = 1
anView?.rightCalloutAccessoryView = cpa.annotationButton
for view in anView?.subviews {
view.removeFromSuperView()
}
anView?.addSubview(cpa.notificationCount)
anView?.addSubview(icon)
anView?.frame = CGRect(x: 0, y:0, width:32, height:32)
anView?.canShowCallout = true
return anView
}