問題は、アニメーションの蓄積にありました。アクティビティモニターは、この問題のデバッグに最も役立ちました。SpringboardのCPU使用率は、100%に達するまで上昇し続けました。そのため、時間は明らかに私のアプリケーションではなく、Springboardにあるレンダリングサーバーに費やされていました。
繰り返し実行回数が非常に多い2つのアニメーションを作成して、永久に実行できるようにしました。次に、各アニメーションを別々のレイヤーに追加しました。アニメーションを作成するために、レイジーチェックを使用し、指定されたキーを使用して既存のアニメーションをレイヤーに要求しました。レイヤーが何も返さない場合は、アニメーションを作成しました。問題は、レイヤーが常に何も返さないことでした。そのため、私はこれらの永遠に繰り返されるアニメーションを作成し続けました。
これは問題のあるコードでした。
// This call always returned nil.
CABasicAnimation *innerRotationAnimation = (CABasicAnimation *)[self.spinnerViewInner.layer animationForKey:@"rotationAnimation"];
// So I kept on creating animations and piling them up.
if (innerRotationAnimation == nil)
{
CATransform3D innerRotationTransform = CATransform3DMakeRotation(0.25f * M_PI * -1, 0, 0, 1.0);
innerRotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
innerRotationAnimation.toValue = [NSValue valueWithCATransform3D:innerRotationTransform];
innerRotationAnimation.duration = 0.25f;
innerRotationAnimation.cumulative = YES;
innerRotationAnimation.repeatCount = HUGE_VALF;
[self.spinnerViewInner.layer addAnimation:innerRotationAnimation forKey:@"rotationAnimation"];
}
この問題を解決するために、既存のアニメーションの削除を開始しました。animationDidStop:finished:
コールバックまたはメソッドの2つのポイントでこれを行うことができ、どちらもsetAnimating:
正常に機能しました。setAnimating:
メソッドの変更は次のとおりです。
- (void)setAnimating:(BOOL)animating
{
if (animating == NO) {
// Remove all existing animations now.
[self.layer removeAllAnimations];
}
else {
CABasicAnimation *animation = // Create animation;
[self.layer addAnimation:animation forKey:@"rotationAnimation"];
}
}
興味のある方は、元のBROKENコードをご覧ください。
- (void)setAnimating:(BOOL)animating
{
if (self.isAnimating == animating)
{
return;
}
_animating = animating;
if (self.isAnimating == YES)
{
CABasicAnimation *innerRotationAnimation = (CABasicAnimation *)[self.spinnerViewInner.layer animationForKey:@"rotationAnimation"];
CABasicAnimation *outerRotationAnimation = (CABasicAnimation *)[self.spinnerViewOuter.layer animationForKey:@"rotationAnimation"];
if (innerRotationAnimation == nil)
{
CATransform3D innerRotationTransform = CATransform3DMakeRotation(0.25f * M_PI * -1, 0, 0, 1.0);
innerRotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
innerRotationAnimation.toValue = [NSValue valueWithCATransform3D:innerRotationTransform];
innerRotationAnimation.duration = 0.25f;
innerRotationAnimation.cumulative = YES;
innerRotationAnimation.repeatCount = HUGE_VALF;
[self.spinnerViewInner.layer addAnimation:innerRotationAnimation forKey:@"rotationAnimation"];
}
if (outerRotationAnimation == nil)
{
CATransform3D outerRotationTransform = CATransform3DMakeRotation(0.25f * M_PI * -1, 0, 0, -1.0);
outerRotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
outerRotationAnimation.toValue = [NSValue valueWithCATransform3D:outerRotationTransform];
outerRotationAnimation.duration = 0.25f;
outerRotationAnimation.cumulative = YES;
outerRotationAnimation.repeatCount = HUGE_VALF;
[self.spinnerViewOuter.layer addAnimation:outerRotationAnimation forKey:@"rotationAnimation"];
}
}
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
self.spinnerViewInner.layer.opacity = (self.isAnimating ? 1.0 : 0.0);
self.spinnerViewOuter.layer.opacity = (self.isAnimating ? 1.0 : 0.0);
}
しかし、私がまだ興味を持っていることが1つあります。特定のキーに対してアクティブなアニメーションは1つしかないため、同じキーで新しいアニメーションを追加しようとしたときに、Core Animationによって既存のアニメーションが削除されるべきではありませんか?そして、なぜまったくanimationForKey:
戻ってこなかったのか。nil