2
votes

As far as I know, there isn't a way to move an annotation without removing & re-adding it to the MapView (Maybe I'm wrong).

Is there a way to prevent the MapView from being re-drawn between removing & re-adding the annotation? Right now the re-draw after removing the annotation causes a frame without the annotation, so it appears to flicker.

I need a solution that works in iOS 3.1 updates.

Thanks

3

3 Answers

5
votes

I figured out how achieve flicker free annotation "updates" using the below code. In a nut shell, you add your new pin FIRST, then delete the old one AFTER. I haven't streamlined my code yet but you'll get the idea.

-(void)replacePin:(NSString *)title SubTitle:(NSString *)subTitle Location:(CLLocationCoordinate2D)location PinType:(MapAnnotationType)pinType Loading:(BOOL)loading Progress:(float)progress
{
    //Find and "decommission" the old pin... (basically flags it for deletion later)
    for (MyMapAnnotation *annotation in map.annotations) 
    {
        if (![annotation isKindOfClass:[MKUserLocation class]])
        {
            if ([annotation.title isEqualToString:title])
                annotation.decommissioned = YES;
        }
    }

    //add the new pin...
    MyMapAnnotation *stationPin = nil;
    stationPin = [[MyMapAnnotation alloc] initWithCoordinate:Location
                                              annotationType:pinType
                                                       title:title
                                                    subtitle:subTitle
                                                     loading:loading
                                              decommissioned:NO
                                                    progress:progress];
    [map addAnnotation:stationPin];
    [stationPin release];
}

Then AFTER, I make the call to search for and remove any decommissioned pins:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKAnnotationView* annotationView = nil;

    if (![annotation isKindOfClass:[MKUserLocation class]])
    {
        MyMapAnnotation* annotation = (MyMapAnnotation*)annotation;

        //your own details...

        //delete any decommissioned pins...
        [self performSelectorOnMainThread:@selector(deletePin:) withObject:annotation.title waitUntilDone:NO];
    }
    return annotationView;

}

And finally, in the background get rid of the old pin:

-(void)deletePin:(NSString *)stationCode
{
    for (MyMapAnnotation *annotation in map.annotations) 
    {
        if (![annotation isKindOfClass:[MKUserLocation class]])
        {
            if ([annotation.title isEqualToString:stationCode])
            {  
                if (annotation.decommissioned)
                    [map removeAnnotation:annotation];
            }
        }
    }
}
12
votes

in iOS4

[theAnnotation setCoordinate:newCoordinate];
1
votes

For 3.1 you'll have to hack. I'd see two possibilities, either trying to force change the coordinates of the current annotation by lurking around in the header files and accessing the memory directly, or fiddling with UIWindow and graphic contexts to try to avoid the drawing done in next runloop cycle to actually reach the screen.

Edit: a third alternative, which might be the easiest, is to do your own lightweight annotation implementation outside of MapKit..