animationDidStop用于组动画

时间:2012-08-28 16:59:10

标签: iphone ios core-animation uiviewanimation

我有一个群组动画,但我无法检测到何时点击animationDidStop。我的代码示例:

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

你们中的任何人都知道我怎么知道组动画何时完成?

3 个答案:

答案 0 :(得分:13)

您还需要将animationName属性设置为匹配,并确保正确定义了委托函数:

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
  }
 }
}

请注意,对于群组动画,您的组件动画上设置的代表将被忽略。

答案 1 :(得分:2)

我提出了一种组织动画完成代码的方法,该代码非常有效。首先,我为动画完成时运行的代码块定义了一个自定义类型:

typedef void (^animationCompletionBlock)(void);

我定义了一个常量,用于为我的动画添加自定义键值对:

#define kAnimationCompletionBlock @"animationCompletionBlock"

然后,当我创建一个动画时,如果我希望它在完成时执行一段代码,我会在我的动画中添加一个自定义属性,其中包含我想要执行的代码块:

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

我将视图控制器设置为动画的委托:

myAnimation.delegate = self

最后,我编写了一个通用动画完成方法,该方法查找附加到动画的动画完成块,并在找到它时执行它:

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

除了非常干净之外,此方法还允许您的动画完成代码访问位于您定义块的范围内的局部变量。这解决了将信息传递给完成方法的问题,这可能很困难。

您可以在我发布到Github的工作示例程序中看到此技术:

<强> Core Animation demo on Github, including completion block code

答案 2 :(得分:2)

我使用此类别来设置完成,如下所示:

[group setCompletionBlock:^{

}];

第一个CAAnimationGroup + Blocks.h:

#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>

typedef void (^TIFAnimationGroupCompletionBlock)();

@interface CAAnimationGroup (Blocks)

- (void)setCompletionBlock:(TIFAnimationGroupCompletionBlock)handler;

@end

和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