2

I have a moving annotation on a MKMapView showing the current user location. I set up my own image for that annotation and I want to rotate it so that you can see the heading.

In the viewForAnnotation delegate, I have:

static NSString *planeIdentifier = @"Plane";
static NSString *stationIdentifier = @"Station";
NSString *identifier;

if([[annotation title] rangeOfString:@"Plane" options:NSLiteralSearch].location == NSNotFound) {
    identifier = stationIdentifier;
}
else {
    identifier = planeIdentifier;
}

MKAnnotationView *annotationView = (MKAnnotationView *) [aMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
    annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
    annotationView.annotation = annotation;
}

annotationView.enabled = YES;

annotationView.canShowCallout = NO;
    annotationView.image = [UIImage imageNamed:@"airPlane.png"];

return annotationView;

The code for calling the instance method is the following:

[planeAnnotation setCoordinate:planeCoordinate];
MKAnnotationView* planeView = [self mapView:mapView viewForAnnotation:planeAnnotation];
[planeView setTransform:CGAffineTransformMakeRotation([[[self modele] udpData] getValueFor:HDING_TRUE item:DYNAMICS]*(M_PI/180))];

The problem is the heading is never updated i.e. the image never rotates.

Any help much appreciated!

EDIT: I have tried setting a custom identifier (the title of the annotation) for each MKAnnotationView I have on the mapView (a few hundred), but I noticed the annotationView is always nil, meaning it doesn't actually dequeue anything from it. I think this is the reason why it doesn't rotate, since i'm not rotating the same MKAnnotationView I am displaying on the map.

bentroc
  • 61
  • 5
  • Where and when does `heading` change? Are all the hundreds of annotations supposed to rotate or just one? Will hundreds be visible all at once? See [this related question](http://stackoverflow.com/questions/6808792/change-uiimage-from-mkannotation-in-the-mkmapview) the answer to which suggests using the `viewForAnnotation` _instance_ method to retrieve the current view and you can try transforming it in real time instead of removing and adding again. –  Jul 16 '12 at 20:30
  • Hello Anna, to answer your questions, the `heading` variable changed 20 times per second, it is a value received on a UDP port. Only one annotation is supposed to rotate, the one showing the movement of the user on the map. All the others are fixed stations. They are not all visible at once, you need to scroll the map. I have tried using the instance method to transform the view, but nothing changed. I think the problem may come from the fact my MKAnnotationView are not properly reused, causing an other (now hidden) view to be edited. – bentroc Jul 16 '12 at 20:40
  • I have edited my code to show you a unique identifier is now used for each MKAnnotationView. When calling the instance method, the line `annotationView.annotation = annotation;` is never called, showing the MKAnnotationView is never reused. – bentroc Jul 16 '12 at 20:44
  • You seem to have only two types (uses) of annotations: one that rotates and others that don't. So I think you should have only two re-use ids. Before you call dequeue (and set image and transform), you look at the annotation to determine what type it is and then set the reuse id (and other logic) accordingly. As to why transforming the view instance when the heading changes doesn't work: posting that code may help. –  Jul 16 '12 at 20:51
  • I have now updated the code to show you the maximum. I see that I'm actually not calling the instance method but the delegate method once again. It may be the source of the problem! – bentroc Jul 16 '12 at 21:13
  • Yes, the problem was there, thank you. – bentroc Jul 16 '12 at 21:22
  • Try this: `MKAnnotationView* planeView = [mapView viewForAnnotation:planeAnnotation];` Note that calling that instance method will still call the delegate method underneath. Also: you still have to do the transform in the delegate method as well (if annotation is "plane"). Also: To check NSString equality, it's easier to use `isEqualToString`. –  Jul 16 '12 at 21:24
  • Why exactly is it necessary to do the transformation in the delegate method also? – bentroc Jul 16 '12 at 21:37
  • Because the map view will/may also call the delegate method itself any time it needs the view even when you don't explicitly update it when the heading updates. –  Jul 16 '12 at 23:10

1 Answers1

4

To answer my question, the problem lied in the fact I was calling the delegate method MKAnnotationView* planeView = [self mapView:mapView viewForAnnotation:planeAnnotation];instead of calling the instance method MKAnnotationView* planeView = [mapView viewForAnnotation:planeAnnotation]; when transforming the MKAnnotationView.

bentroc
  • 61
  • 5