animationDidStop pour l'animation de groupe

J'ai une animation de groupe mais je ne peux pas la détecter quand elle frappe animationDidStop. exemple de mon code:

[group setDelegate:self]; [view.layer addAnimation:group forKey:@"groupAnimation"]; 

l'un d'entre vous sait comment je sais quand l'animation de groupe est terminée?

Vous devez également définir la propriété animationName à faire correspondre et assurez-vous que votre fonction de délégué est correctement définie:

 CAAnimationGroup *group = [CAAnimationGroup animation]; group.duration = 2.0f; group.delegate = self; [group setValue:@"groupAnimation" forKey:@"animationName"]; [group setAnimations:[NSArray arrayWithObjects:myAnimation, myOtherAnimation, nil]]; [view.layer addAnimation:group forKey:@"groupAnimation"]; 

. . .

 - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished { if (finished) { NSSsortingng *animationName = [animation valueForKey:@"animationName"]; if ([animationName isEqualToSsortingng:@"groupAnimation"]) { // your groupAnimation has ended } } } 

Veuillez noter qu'avec les animations de groupe, les delegates définis sur les animations de vos composants seront ignorés.

J'utilise cette catégorie pour définir l'achèvement comme ceci:

 [group setCompletionBlock:^{ }]; 

Premier CAAnimationGroup + Blocks.h:

 #import <QuartzCore/QuartzCore.h> #import <objc/runtime.h> typedef void (^TIFAnimationGroupCompletionBlock)(); @interface CAAnimationGroup (Blocks) - (void)setCompletionBlock:(TIFAnimationGroupCompletionBlock)handler; @end 

Et CAAnimationGroup + Blocks.m:

 #import "CAAnimationGroup+Blocks.h" static char CAAnimationGroupBlockKey; @implementation CAAnimationGroup (Blocks) - (void)setCompletionBlock:(TIFAnimationGroupCompletionBlock)handler { objc_setAssociatedObject(self, &CAAnimationGroupBlockKey, handler, OBJC_ASSOCIATION_COPY_NONATOMIC); self.delegate = self; } - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished { if (finished) { TIFAnimationGroupCompletionBlock handler = (TIFAnimationGroupCompletionBlock)objc_getAssociatedObject(self, &CAAnimationGroupBlockKey); if (handler) { handler(); } } } @end 

J'ai trouvé un moyen d'organiser le code d'achèvement de l'animation qui fonctionne vraiment bien. D'abord, j'ai défini un type personnalisé pour qu'un bloc de code s'exécute quand une animation se termine:

 typedef void (^animationCompletionBlock)(void); 

Je définis une constante que j'utilise pour append une paire key-valeur personnalisée à mon animation:

 #define kAnimationCompletionBlock @"animationCompletionBlock" 

Ensuite, lorsque je crée une animation, si je veux qu'elle exécute un bloc de code lorsqu'elle se termine, j'ajoute une propriété personnalisée à mon animation qui contient le bloc de code que je veux exécuter:

 animationCompletionBlock theBlock; theBlock = ^void(void) { someButton.enabled = TRUE; NSLog(@"Animation complete"); //whatever other code you want to do on completion } [myAnimation setValue: theBlock forKey: kAnimationCompletionBlock]; 

J'ai défini le controller de vue comme étant le délégué de l'animation:

 myAnimation.delegate = self 

Enfin, j'écris une méthode d'achèvement d'animation polyvalente qui cherche un bloc d'achèvement d'animation attaché à l'animation, et l'exécute s'il le trouve:

 /* This method looks for a value added to the animation that just completed with the key kAnimationCompletionBlock. If it exists, it assumes it is a code block of type animationCompletionBlock, and executes the code block. This allows you to add a custom block of completion code to any animation or animation group, rather than Having a big complicated switch statement in your animationDidStop:finished: method with global animation ompletion code. (Note that the system won't call the animationDidStop:finished method for individual animations in an animation group - it will only call the completion method for the entire group. Thus, if you want to run code after part of an animation group completes, you have to set up a manual timer.) */ - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag { animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock]; if (theBlock) theBlock(); } 

En plus d'être très propre, cette approche permet également à votre code d'achèvement d'animation d'accéder aux variables locales qui se trouvent dans la scope où vous définissez le bloc. Cela résout le problème de transmettre des informations à votre méthode d'achèvement, ce qui peut être difficile.

Vous pouvez voir cette technique dans un exemple de programme que j'ai posté sur Github:

Démo Core Animation sur Github, incluant le code de bloc d'achèvement