Force MKMapView viewForAnnotation to update

cocoa-touch, ios, mkannotation, mkannotationview, mkmapview

Solution

Due to the way the map view caches its annotations, you NEED to remove and re-add the annotation if you need to make changes to its appearance. A simple remove & add is the way to go. There is no cache invalidating mechanism but this.

Problem

So I have a MKMapView with all my pins added, and the colour of the pin is dependent on whether a value is set for that pin. When I first load the app, `viewForAnnotation` is called and the colours are set accordingly. However, when I update the pin's details (such as location, title, etc...) I also update the pinColour to find it doesn't update. It looks like `viewForAnnotation` isn't called again after the initial add. I have read many questions similar to this and I can confirm that `mapView.delegate = self;` Here is my `viewForAnnotation` code: ``` - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MapAnnotation *)annotation { if([annotation class] == MKUserLocation.class) return nil; NSString *pinIdentifier = annotation.identifier; // This is a unique string for each pin and is getting populated every time! MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:pinIdentifier]; if(annotationView == nil) annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinIdentifier]; else annotationView.annotation = annotation; // Never had this line fire... annotationView.canShowCallout = YES; annotationView.animatesDrop = NO; annotationView.enabled = YES; annotationView.tag = annotation.counter; if(annotation.pinColour == Stopped) // from enum annotationView.pinColor = MKPinAnnotationColorRed; else annotationView.pinColor = MKPinAnnotationColorGreen; UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; [infoButton addTarget:self action:@selector(mapCalloutButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; infoButton.tag = annotation.counter; annotationView.rightCalloutAccessoryView = infoButton; return annotationView; } ``` Here is the code where I add the pin: ``` CLLocationCoordinate2D annotationCoord; annotationCoord.latitude = latestPosition.latitude; annotationCoord.longitude = latestPosition.longitude; MapAnnotation *annotation = [[MapAnnotation alloc] init]; annotation.coordinate = annotationCoord; annotation.identifier = theIdentifier; annotation.title = theTitle; annotation.subtitle = theSubtitle annotation.pinColour = [self getPinColour]; annotation.counter = theCounter; [theMapView addAnnotation:annotation]; ``` Here is the code where I update the pin (different method to add): ``` updatePin = true; pinCounter = mapPin.counter; CLLocationCoordinate2D annotationCoord; annotationCoord.latitude = latestPosition.latitude; annotationCoord.longitude = latestPosition.longitude; [mapPin setCoordinate:annotationCoord]; mapPin.identifier = theIdentifier; mapPin.subtitle = theSubtitle; mapPin.pinColour = [self getPinColour]; ``` I'm not sure what I'm missing. `viewForAnnotation` is obviously working, it's just not ever called after the initial add! If it were to call this function I'm 100% sure it would work as it does the colour change if I restart the app! EDIT: Oh and I really don't want to start removing annotations and re-adding them. It's what I'm doing in the short term anyway!

Original source

Related problems