CoreAnimationでCALayerを動かし続けたい時の方法です。プロパティ変更での暗黙的なアニメーションだといろいろと不都合なので、CABasicAnimationを使ってやってみました。
以下がそのサンプルです。カスタムビューにアウトレットをつなげて実行してください。
// // EndlessCoreAnimationTest.h // #import <Cocoa/Cocoa.h> #import <QuartzCore/QuartzCore.h> @interface EndlessCoreAnimationTest : NSObject { IBOutlet NSView *view; CALayer *moveLayer; NSTimer *timer; NSDate *startDate; } - (void)changeAnimation; @end // // EndlessCoreAnimationTest.m // #import "EndlessCoreAnimationTest.h" @implementation EndlessCoreAnimationTest - (void)awakeFromNib { NSRect viewRect = [view bounds]; CGFloat viewWidth = viewRect.size.width; CGFloat viewHeight = viewRect.size.height; CGFloat minSize = (viewWidth > viewHeight) ? viewHeight : viewWidth; CALayer *baseLayer = [CALayer layer]; CGColorRef baseColor = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0); baseLayer.backgroundColor = baseColor; CGColorRelease(baseColor); moveLayer = [CALayer layer]; moveLayer.anchorPoint = CGPointMake(0.5, - 9.0); moveLayer.bounds = CGRectMake(0, 0, minSize * 0.05, minSize * 0.05); moveLayer.position = CGPointMake(viewWidth * 0.5, viewHeight * 0.5); CGColorRef moveColor = CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0); moveLayer.backgroundColor = moveColor; CGColorRelease(moveColor); [view setLayer:baseLayer]; [view setWantsLayer:YES]; [baseLayer addSublayer:moveLayer]; [self performSelector:@selector(startTimer) withObject:nil afterDelay:1.0]; } - (void)startTimer { startDate = [[NSDate date] retain]; [self changeAnimation]; timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changeAnimation) userInfo:nil repeats:YES]; } - (void)changeAnimation { CGFloat currentTime = [startDate timeIntervalSinceNow]; CGFloat duration = 2.0; CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"]; CATransform3D fromTrans = CATransform3DMakeRotation(currentTime * M_PI / 4.0, 0.0, 0.0, 1.0); CATransform3D toTrans = CATransform3DMakeRotation((currentTime - duration) * M_PI / 4.0, 0.0, 0.0, 1.0); anim.fromValue = [NSValue valueWithCATransform3D:fromTrans]; anim.toValue = [NSValue valueWithCATransform3D:toTrans]; anim.duration = duration; [moveLayer addAnimation:anim forKey:@"transformAnimation"]; } - (void) dealloc { [timer invalidate]; [startDate release]; [super dealloc]; } @end
durationを2秒にしてtoValueを2秒後の値にしたCABasicAnimationを、NSTimerで1秒ごとに途切れる事無く追加しています。追加する時に動いているアニメーションの位置が新たなアニメーションのfromValueと一致するようになっていればスムーズにつながります。