Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

animationDidStop for group animation

I have a group animation but I can not detect when hits animationDidStop. example of my code:

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

any of you knows how I know when the group animation is done?

like image 541
Juan Avatar asked Dec 03 '22 02:12

Juan


2 Answers

You need to also set the animationName property to match, and ensure that your delegate function is properly defined:

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)
 {
  NSString *animationName = [animation valueForKey:@"animationName"];
  if ([animationName isEqualToString:@"groupAnimation"])
  {
   // your groupAnimation has ended
  }
 }
}

Please note that with group animations, the delegates set on your component animations will be ignored.

like image 172
CSmith Avatar answered Dec 15 '22 20:12

CSmith


I came up with a way to organize animation completion code that works really well. First, I defined a custom type for a block of code to run when an animation completes:

typedef void (^animationCompletionBlock)(void);

I define a constant that I use to add a custom key-value pair to my animation:

#define kAnimationCompletionBlock @"animationCompletionBlock"

Then, when I create an animation, if I want it to execute a block of code when it finishes, I add a custom property to my animation that contains the block of code I want to execute:

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];

I set the view controller to be the animation's delegate:

myAnimation.delegate = self

Finally, I write a general-purpose animation completion method that looks for an animation completion block attached to the animation, and executes it if it finds it:

/*
 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();
}

In addition to being very clean, this approach also lets your animation completion code have access to local variables that are inside the scope where you define the block. That solves the problem of passing information to your completion method, which can be difficult.

You can see this technique in a working example program I posted to Github:

Core Animation demo on Github, including completion block code

like image 28
Duncan C Avatar answered Dec 15 '22 20:12

Duncan C