UIViewでのアニメーションiOS4.0対応版

UIViewに実装されているアニメーション関連のメソッドがiOS4.0から刷新され、今までのメソッドは非推奨になってしまった。
そこで、"UIView アニメーション"でググって一番上にくるUIViewで手軽にアニメーションを実行する方法 - プログラミングノートを参照させてもらいつつ、その違いについてまとめてみる。

既存の書き方

前述のid:ntakuさんのところから引用させてもらうとこんな感じ。

-(void)startAnimation:(id)sender{
  UIButton *btn = (UIButton *)sender;
	
  //アニメーションの対象となるコンテキスト
  CGContextRef context = UIGraphicsGetCurrentContext();
  [UIView beginAnimations:nil context:context];
  //アニメーションを実行する時間
  [UIView setAnimationDuration:0.5];
  //アニメーションイベントを受け取るview
  [UIView setAnimationDelegate:self];
  //アニメーション終了後に実行される
  [UIView setAnimationDidStopSelector:@selector(endAnimation)];

  //TODO: 
  [btn setCenter:CGPointMake(0,0)];

  // アニメーション開始
  [UIView commitAnimations];	
}

この場合、0.5秒かけてUIButtonが(0, 0)に移動するアニメーションが実行される。

iOS4.0以降

ここで出てきたsetAnimationなんとかというクラスメソッドがiOS4.0以降では推奨されていないため、同一の事を実行するにはこういう書き方になる。

長いので改行してしまってるものの、1行。簡潔。
最大の違いは、アニメーションの内容がBlocksでくくられていること。このBlocks自体もiPhoneアプリ開発ではOS3.2から有効になった書き方なので各種入門書籍にはあまり情報がなく、見慣れない人も多いかもしれない。Blocksについてくわしくは別エントリにまとめたいけど、ひとまずは公式ドキュメントを参照のこと。
今までの書き方だと、パッと見よくわからないものがアニメーションの内容の前後にあり今一歩まとまりがなかったのが、アニメーションの処理自体は1行に収まるため読みやすくなっていると思う。

アニメーションのクラスメソッド

iOS4.0以降で新たに加わったBlocksを使ったアニメーションのメソッド自体は次の5つが用意されていて、やりたいことの複雑さで使い分けられると思う。

+ animateWithDuration:delay:options:animations:completion:
+ animateWithDuration:animations:completion:
+ animateWithDuration:animations:
+ transitionWithView:duration:options:animations:completion:
+ transitionFromView:toView:duration:options:completion:

最初3つがアニメーション、残り2つがviewの切り替え用。

最初の長ったらしいやつでもObjective-Cだから長いってだけで、むしろそれぞれの引数の意味は明確だし、それさえ理解してしまえばだいたいのアニメーションはカバーできそう。だいたい以下の感じ。

  • 最初の引数durationは今まで通り、アニメーションに要する時間を指定
  • 次のdelayはアニメーション開始時までの時間を指定
  • optionsはアニメーションを繰り返すUIViewAnimationOptionRepeatやアニメーションを巻き戻すUIViewAnimationOptionAutoreverseなんかが指定できる
  • その次のanimationsで実際のアニメーションをblockで渡す
  • 最後のcompletionはアニメーション終了時に呼び出される動作をこれまたblockで渡す

やはり、今までは複数行で指定していたアニメーションの要素が一つのメソッドにまとまっていることがわかる。
blockを引数で渡すため、例えばアニメーションの中身が複雑になった読みづらくなってしまうかもしれない。その場合は、あらかじめアニメーション処理をまとめて記述したblockを宣言しておいて、引数でそれを渡すようにすればよさそう。こんな感じかしら(動作未確認)。そうすればコードの可読性も上がりますね。

-(void)startAnimation:(id)sender{
  UIButton *btn = (UIButton *)sender;

  void (^chainAnimations)(void) = { view.center = CGPointMake(0,0);
  // 何かアニメーション
  // 何かもっとアニメーション
  }

  [btn animateWithDuration:0.5 animations:chainAnimations ];
}

まとめ

今回のアニメーション関連のメソッドの場合もそうだけど、ドキュメント内にもたびたび登場してきているBlocksをうまく使うことが推奨されているような印象のiPhoneアプリ開発。より便利に書けそう、よりわかりやすい書き方ができそうで、精進のしがいがありますね。プライベートの開発だけでは時間が足りませんね。