Determina el final de un ciclo de animation.

Este fue un poco difícil de search. No estoy seguro de qué golpear en Google o SO, así que me disculpo si esto ha sido respondido antes.

Entonces tengo dos animaciones que aplico a un CALayer con una duración de 5 segundos (aunque esto no es relevante) y se repiten indefinidamente. Quiero poder eliminar con gracia estas animaciones en la interacción del usuario.

Detectar la interacción es fácil, pero no es tan fácil determinar cuándo las animaciones han llegado al final de un ciclo. Al detectar esto, espero lograr el efecto de la animation terminando su último ciclo y deteniéndolo, en lugar de eliminarlo severamente de la pantalla que simplemente parece poco amistosa.

Esto es lo que estoy haciendo ahora y no está funcionando

 - (void)attachFadeAnimation { // Create a fade animation that compliments the scale such that // the layer will become totally transparent 1/5 of the way // through the animation. CAKeyframeAnimation *fadeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; fadeAnimation.values = @[@0.8, @0, @0]; [self addAnimation:fadeAnimation withKeyPath:@"opacity"]; } - (void)addAnimation:(CAKeyframeAnimation *)animation withKeyPath:(NSString *)keyPath { // These are all shanetworking values of the animations and therefore // make more sense to be added here. Any changes here will // change each animation. animation.keyTimes = @[@0, @0.2, @1]; animation.repeatCount = HUGE_VALF; animation.duration = 5.0f; animation.delegate = self; [self.layer addAnimation:animation forKey:keyPath]; } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if ( !self.emanating ) [self.layer removeAllAnimations]; } 

La llamada del delegado a animationDidStop:finished no se llama cuando esperaba. Claramente he entendido mal la documentation.

Ok, así que al fallar con el uso de methods de delegado para lograr esto, busqué a través de la documentation de Apple CoreAnimation para descubrir que el CALayer asociado con mi vista tiene una propiedad presentationLayer que describe lo que se está mostrando actualmente en la pantalla.

Usando esto, pude crear otra animation para "terminar" con más gracia la primera animation.

Este código es en realidad de un file diferente al original, pero el efecto que quería lograr es el mismo:

 - (void)alert { CABasicAnimation *flashAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; flashAnimation.duration = 1.0f; flashAnimation.autoreverses = YES; flashAnimation.repeatCount = HUGE_VALF; flashAnimation.fromValue = (id)self.view.backgroundColor.CGColor; flashAnimation.toValue = (id)[UIColor colorWithRed:0.58f green:0.23f blue:0.14f alpha:1.0f].CGColor; [self.view.layer addAnimation:flashAnimation forKey:@"alert"]; } - (void)cancelAlert { // Remove the flashing animation from the view layer. [self.view.layer removeAnimationForKey:@"alert"]; // Using the views presentation layer I can interpolate the background // colour back to the original colour after removing the flashing // animation. CALayer *presentationLayer = (CALayer *)[self.view.layer presentationLayer]; CABasicAnimation *resetBackground = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; resetBackground.duration = 1.0f; resetBackground.fromValue = (id)presentationLayer.backgroundColor; resetBackground.toValue = (id)_originalBackgroundColor.CGColor; [self.view.layer addAnimation:resetBackground forKey:@"reset"]; }