UIView アニメーションにBlocks が使えると、とても便利なのですが、iOS 3 デバイスをサポートする関係上、なかなか使用する機会がありませんでした。
今回初めて使用してみたので、その使い方を書いてみたいと思います。
Blocks の詳細については、ドキュメントが日本語化されているので、そちらをご覧下さい。
UIView アニメーション Blocks 以前
複数のアニメーションを直列につなげて実行させたい場合、beginAnimations:context: と commitAnimations メソッドを使用すると、以下のように一つのアニメーション毎にメソッドを用意してやったりします。これだと見通しが悪いし、繋げるアニメーションが多いと絶望的に面倒くさいです。
// 一番最初のアニメーション開始場所
- (void)startAnimation
{
someView.frame = CGRectMake(0,-40,480,40);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:ctx];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(endAnimation1)]; // 次のアニメーション開始メソッド
someView.frame = CGRectMake(0,0,480,40);
[UIView commitAnimations];
}
// 前のアニメーションの終わりに呼ばれるメソッド
// ここが次のアニメーションの開始場所
- (void)endAnimation1
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:ctx];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:3.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(endAnimation2)];
someView.frame = CGRectMake(0,1,480,40);
[UIView commitAnimations];
}
// ・・・以下続く
UIView アニメーション Blocks 以後
対して、animateWithDuration:animations:completion: メソッドだとどうでしょうか?
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completionanimations: の後にアニメーション処理をブロックで、completion: の後にアニメーション後の処理をブロックで指定します。
複数のアニメーションを直列につなげる場合は、以下のようにします。
UIView *someView = ビューをインスタンス化してローカル変数に退避;
someView.frame = CGRectMake(0,-40,480,40);
[self.view addSubview:someView];
[UIView animateWithDuration:0.5
animations:^{someView.frame = CGRectMake(0,0,480,40);}
completion:^(BOOL finished) {
[UIView animateWithDuration:3.0
animations:^{someView.frame = CGRectMake(0,1,480,40);}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.5
animations:^{someView.frame = CGRectMake(0,-40,480,40);}
completion:^(BOOL finished) {
[someView removeFromSuperview];
}]; }]; }];
ずいぶん見通しが良くなりました。 まあ、最後の括弧が見ため悪いですが、一連のアニメーションを一つのメソッド内で記述できてしまうのは楽です。
さらに特筆すべきは、メソッド内のローカル変数(someView)にブロック内からもアクセスできるという点です。
詳しい仕組みは Blocks のドキュメントに譲りますが、大雑把に言うとブロック内からアクセスするローカル変数(スタック上にある変数)はコピーされて保存され、そのブロックが生きている限り保持されるようです。更にヒープ領域にあるオブジェクトには、retain して保持するようです。(ブロックの消滅とともに release するもよう)
最後に、上記2つ目アニメーションで、Y座標を1だけ動かすのに3秒を割り当てているのは、ウエイトの代わりです。ここを仮に CGRectMake(0,0,480,40)のままにしたり、何も命令を記述しないと、3秒を待たず直ぐに completion ブロックが起動されてしまいます。
0 件のコメント:
コメントを投稿