2012-11-21 30 views
0

我有一个应用程序在使用约30-35分钟后会减慢整个操作系统。滞后是渐进的,我可以看到它随着时间的推移而增加,因为我一遍又一遍地重复同样的操作。这是一款音乐应用程序,在流过大约15-20首曲目后,延迟是无法忍受的。长时间使用后应用程序和操作系统滞后

在UIScrollView中滚动项目时,帧频会降到10以下。很多帧被跳过,用户界面几乎锁定。如果我为应用程序提供背景,那么SpringBoard中的操作系统以及基本上任何地方都会出现这种滞后现象。在SpringBoard中滚动应用程序图标变得不连贯。解锁幻灯片变得波涛汹涌,等等。

我该如何解决这个问题?可能是什么原因。由于代码库相当复杂,我无法削减代码以创建最小可重现的示例。我需要帮助了解可能导致操作系统几乎锁定的原因。这不是一个僵局,因为用户界面仍然响应,但只是需要很长时间。

什么分析工具可以帮助照亮这个问题的原因?我怀疑它可能是因为内存泄漏,但令人惊讶的是操作系统没有发送应用程序内存警告,所以我也不完全确定。

任何帮助,非常感谢。

回答

2

问题在于构建动画。活动监视器在调试此问题时非常有用。 Springboard的CPU使用率一直在上升,直到达到100%。所以时间显然不是在我的应用程序中花费的,而是在Springboard中的渲染服务器上。

我创建了两个带有巨大重复次数的动画,让它们永远运行。然后我将每个动画添加到一个单独的图层。为了创建动画,我使用了一个懒惰检查,并使用给定的键向图层询问任何现有的动画。如果图层没有任何返回,我创建了动画。问题是该层总是没有返回任何东西,所以我一直创造这些永远重复的动画。

这是有问题的代码。

// 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:回调,或在我的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); 
} 

虽然有一点我仍然很好奇。由于给定键只能有一个活动动画,因此当我尝试使用相同的键添加新动画时,Core Animation是否应该删除我的现有动画?为什么animationForKey:完全返回nil

1
+0

我正在使用包括Time Profiler,Core Animation,Open GL ES在内的各种工具,但它们并未指出任何问题区域。设备利用率保持在10-20%左右,所以我不会对GPU施加压力。时间事件探查器不会显示任何明显的增加每次迭代的工作量,所以这也没有帮助。你知道我可以用什么其他工具来调试更多吗? – Anurag

+0

分配,泄漏和活动监视器。 – CuriousRabbit

+0

感谢您的提示。 Activity Monitor是一个很好的开始,让我朝着正确的方向前进。 – Anurag

相关问题