Como faço para animar a queda do MKAnnotationView?

Eu tenho um personalizado MKAnnotationView onde eu defino minha imagem em viewForAnnotation. Como faço para animar a queda como eu posso com o MKPinAnnotationView?

Meu código é

- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id )annotation { static NSString *AnnotationViewID = @"annotationViewID"; MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID]; if (annotationView == nil) { annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease]; } annotationView.image = [UIImage imageNamed:@"blah.png"]; annotationView.annotation = annotation; return annotationView; } 

Implemente o método delegado didAddAnnotationViews e faça a animação você mesmo:

 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)annotationViews { for (MKAnnotationView *annView in annotationViews) { CGRect endFrame = annView.frame; annView.frame = CGRectOffset(endFrame, 0, -500); [UIView animateWithDuration:0.5 animations:^{ annView.frame = endFrame; }]; } } 

Um problema com o código acima, de Anna Karenina, é que ele não lida quando você adiciona annotations abaixo de onde o usuário está olhando no momento. Essas annotations flutuam no ar antes de serem descartadas porque são movidas para o mapa visível do usuário.

Outra é que também cai o ponto azul do local do usuário. Com esse código abaixo, você manipula a localização do usuário e grandes quantidades de annotations de mapa fora da canvas. Eu também adicionei um bom salto;)

 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { MKAnnotationView *aV; for (aV in views) { // Don't pin drop if annotation is user location if ([aV.annotation isKindOfClass:[MKUserLocation class]]) { continue; } // Check if current annotation is inside visible map rect, else go to next one MKMapPoint point = MKMapPointForCoordinate(aV.annotation.coordinate); if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) { continue; } CGRect endFrame = aV.frame; // Move annotation out of view aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - self.view.frame.size.height, aV.frame.size.width, aV.frame.size.height); // Animate drop [UIView animateWithDuration:0.5 delay:0.04*[views indexOfObject:aV] options: UIViewAnimationOptionCurveLinear animations:^{ aV.frame = endFrame; // Animate squash }completion:^(BOOL finished){ if (finished) { [UIView animateWithDuration:0.05 animations:^{ aV.transform = CGAffineTransformMakeScale(1.0, 0.8); }completion:^(BOOL finished){ if (finished) { [UIView animateWithDuration:0.1 animations:^{ aV.transform = CGAffineTransformIdentity; }]; } }]; } }]; } } 

@ MrAlek’s Answer para swift3

 optional func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) { print(#function) var i = -1; for view in views { i += 1; if view.annotation is MKUserLocation { continue; } // Check if current annotation is inside visible map rect, else go to next one let point:MKMapPoint = MKMapPointForCoordinate(view.annotation!.coordinate); if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) { continue; } let endFrame:CGRect = view.frame; // Move annotation out of view view.frame = CGRect(origin: CGPoint(x: view.frame.origin.x,y :view.frame.origin.y-self.view.frame.size.height), size: CGSize(width: view.frame.size.width, height: view.frame.size.height)) // Animate drop let delay = 0.03 * Double(i) UIView.animate(withDuration: 0.5, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations:{() in view.frame = endFrame // Animate squash }, completion:{(Bool) in UIView.animate(withDuration: 0.05, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in view.transform = CGAffineTransform(scaleX: 1.0, y: 0.6) }, completion: {(Bool) in UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in view.transform = CGAffineTransform.identity }, completion: nil) }) }) } } 

Resposta @mrAlek no Swift:

 func mapView(mapView: MKMapView!, didAddAnnotationViews views: [AnyObject]!) { println("didAddAnnotationViews()") var i = -1; for view in views { i++; let mkView = view as! MKAnnotationView if view.annotation is MKUserLocation { continue; } // Check if current annotation is inside visible map rect, else go to next one let point:MKMapPoint = MKMapPointForCoordinate(mkView.annotation.coordinate); if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) { continue; } let endFrame:CGRect = mkView.frame; // Move annotation out of view mkView.frame = CGRectMake(mkView.frame.origin.x, mkView.frame.origin.y - self.view.frame.size.height, mkView.frame.size.width, mkView.frame.size.height); // Animate drop let delay = 0.03 * Double(i) UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in mkView.frame = endFrame // Animate squash }, completion:{(Bool) in UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in mkView.transform = CGAffineTransformMakeScale(1.0, 0.6) }, completion: {(Bool) in UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in mkView.transform = CGAffineTransformIdentity }, completion: nil) }) }) } } 

@ Resposta do MrAlek em Swift 2:

 func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]) { print(__FUNCTION__) var i = -1; for view in views { i++; if view.annotation is MKUserLocation { continue; } // Check if current annotation is inside visible map rect, else go to next one let point:MKMapPoint = MKMapPointForCoordinate(view.annotation!.coordinate); if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) { continue; } let endFrame:CGRect = view.frame; // Move annotation out of view view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y - self.view.frame.size.height, view.frame.size.width, view.frame.size.height); // Animate drop let delay = 0.03 * Double(i) UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in view.frame = endFrame // Animate squash }, completion:{(Bool) in UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in view.transform = CGAffineTransformMakeScale(1.0, 0.6) }, completion: {(Bool) in UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in view.transform = CGAffineTransformIdentity }, completion: nil) }) }) } }