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 件のコメント:
コメントを投稿