4

グループ アニメーションがありますが、animationDidStop がいつヒットしたかを検出できません。私のコードの例:

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

グループのアニメーションがいつ終了したかを知る方法を知っている人はいますか?

4

3 に答える 3

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

グループ アニメーションでは、コンポーネント アニメーションに設定されたデリゲートは無視されることに注意してください。

于 2012-08-28T20:11:46.927 に答える
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 に投稿した実際のサンプル プログラムで確認できます。

完了ブロック コードを含む、Github の Core Animation デモ

于 2012-09-07T02:01:06.197 に答える
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
于 2015-01-20T17:48:09.173 に答える