グループ アニメーションがありますが、animationDidStop がいつヒットしたかを検出できません。私のコードの例:
[group setDelegate:self];
[view.layer addAnimation:group forKey:@"groupAnimation"];
グループのアニメーションがいつ終了したかを知る方法を知っている人はいますか?
グループ アニメーションがありますが、animationDidStop がいつヒットしたかを検出できません。私のコードの例:
[group setDelegate:self];
[view.layer addAnimation:group forKey:@"groupAnimation"];
グループのアニメーションがいつ終了したかを知る方法を知っている人はいますか?
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
}
}
}
グループ アニメーションでは、コンポーネント アニメーションに設定されたデリゲートは無視されることに注意してください。
私は、非常にうまく機能するアニメーション補完コードを整理する方法を思いつきました。最初に、アニメーションの完了時に実行するコード ブロックのカスタム タイプを定義しました。
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 に投稿した実際のサンプル プログラムで確認できます。
このカテゴリを使用して、次のように補完を設定しています。
[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