Search code examples
objective-cioscore-animation

Why does UIView:animateWithDuration complete immediately?


I have a subclass of MKPointAnnotation with the following method which I run on iOS 4:

- (void)animate {
    [UIView
     animateWithDuration: 3.0
     delay:1.0
     options:UIViewAnimationOptionAllowUserInteraction
     animations:^{
         CLLocationCoordinate2D loc = 
             CLLocationCoordinate2DMake([self coordinate].latitude + 0.001,
                                        [self coordinate].longitude + 0.001);
         [self setCoordinate:loc];

     }
     completion:^(BOOL finished) {
         NSLog(@"Is completed");
     }];
}

It is called by clicking a UIBarButtonItem.

I expect to see the my annotation travel across a MKMapView. However all I see is the annotation in its final resting place when I call the method like this:

[mapView addAnnotation:myAnnotation];
[myAnnotation animate];
[myAnnotation release];

The intended animation only occurs if I call the method like this:

[mapView addAnnotation:myAnnotation];
[myAnnotation performSelector:@selector(animate) withObject:nil afterDelay:0.5];
[myAnnotation release];

Note that I get the unintended behavior if the 'afterDelay', is smaller e.g. < 0.1s.

Any ideas why this could be the case?


Solution

  • The animation ultimately acts on the MKAnnotationView, not the MKAnnotation. Adding an annotation to a MKMapView does not necessarily mean that the corresponding view will be added any time soon.

    Therefore you get crazy behaviour if you attempt to animate a MKAnnotation before its corresponding MKAnnotationView has been added to the MKMapView.

    The solution is to only animate a MKAnnotation once you know its corresponding MKAnnotationView has been added to MKView. You can know this by using MKMapViewDelegate - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views to trigger your animation.