UIViewをぐるぐる回転させるシンプルな方法 (注:追記あり)

新作アプリ用に同期アイコンを作ったので、これを回転させるのに色々調べたのですが、みんなそれぞれ書いていることが少しずつ違って悩んだので、こうするのが一番シンプルだろうというのを書いてみます。

この例ではImageViewのLayerを操作して90度ずつ無限に回転を繰り返します。
任意の角度を指定したい場合はnumberWithFloat:の数値とrepeatCountでうまく調整してください。(90度以下の数値を指定して必要回数繰り返せば良いはず)

    CALayer *layer = imageView.layer; 

    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];   
    animation.toValue = [NSNumber numberWithFloat:M_PI / 2.0];    
    animation.duration = 0.5;           // 0.5秒で90度回転
    animation.repeatCount = MAXFLOAT;   // 無限に繰り返す
    animation.cumulative = YES;         // 効果を累積
    [layer addAnimation:animation forKey:@"ImageViewRotation"];

タイマーを使ったり、アニメーションを繰り返したりせずすっきり書けました。

アニメーションをやめるにはaddAnimation:forKey:で指定したキーを使って以下のように書きます。

    CALayer *layer = imageView.layer;

    [layer removeAnimationForKey:@"ImageViewRotation"];

ただこの場合、回転が元の位置に戻ってしまいます。

アニメーションを任意のタイミングで止めたり、再開したい場合は以下のようにします。
(http://blog.livedoor.jp/tek_nishi/archives/3508878.html を参考にさせて頂きました。)

一時停止

    CALayer *layer = imageView.layer;

    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;

再開

    CALayer *layer = imageView.layer;

    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;

今回はImageViewのlayerを操作するように書いてありますが、UIViewなら基本的になんでもいけると思います。

ちなみに回転だけじゃなくて3D的にアニメーションする場合は以下のように書くと良いみたいです。(この例では回転だけですが)

    CALayer *layer = imageView.layer;
    
    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform"];   
    CATransform3D transform = CATransform3DMakeRotation(0.5 * M_PI, 0.0, 0.0, 1.0);     // 90右回転
    animation.toValue = [NSNumber valueWithCATransform3D:transform];
    
    // 以下はさっきと同じ
    animation.duration = 0.5;           // 0.5秒で90度回転
    animation.repeatCount = MAXFLOAT;   // 無限に繰り返す
    animation.cumulative = YES;         // 効果を累積
    [layer addAnimation:animation forKey:@"ImageViewRotation"];

CALayerはあまり良くわかっていないので間違っている点などあればご指摘ください。

P.S.
停止と再開を参考にさせてもらったこちらのサイトではカテゴリを使ってCALayerを拡張しているので同じように回転もしても良いのかも知れません。

追記

書いた途端にあれですが、もう少しシンプルな方法を教えてもらいました。
90度ずつ回す必要がないのでわかりやすそうです。負けた\(^o^)/

Core Animation で画像を回す