【问题标题】:UIView repeated animateWithDuration CPU 100%UIView 重复 animateWithDuration CPU 100%
【发布时间】:2013-11-24 08:36:18
【问题描述】:

大家好, 小问题。

我创建了一个UIViewAnimatedUIView。 在 init 中,我创建了一个子视图,我像这样设置动画:

   - (void)animateView{
    [UIView animateWithDuration:4.0
                     delay:1.0
                     options: nil
                     animations:^{ 
                         // Animation PART 1
                         } 
                     completion:^(BOOL  completed){
                       [UIView animateWithDuration:4.0
                           animations:^{ 
                               // Animation PART 2
                               } 
                           completion:^(BOOL  completed){
                             [self animateView];
                           }
                         ];
                     }
     ]; 

}

我必须在第二个完成块中自己调用[self animateView],而不是使用选项重复,因为我只想延迟第一个动画1秒。

一切正常,我分配并初始化我的视图并将其添加为子视图,它应该是动画的。

但是,当我关闭我的超级视图时,我猜 ARC 会完成它的工作并释放动画视图,但我的 CPU 会达到 100%! 我进行了调查,如果我对[self animateView] 的调用发表评论,当我关闭超级视图时,我的 CPU 不会飙升。

所以我已经设法解决了这个问题(通过在调用之前放置一个条件并在关闭超级视图之前更改一个布尔值,keepAnimating = NO),我只是想了解它为什么这样做? 为什么它试图保持动画,为什么它使用这么多 CPU? 如果我将 NSLog 放在完成块中,我会每 8 秒第一次看到它,但是当我关闭超级视图时,NSLog 只会每毫秒出现一次......

顺便说一句:它与这个问题有关:UIView animation using 90%CPU,这并没有真正得到回答。非常感谢!

【问题讨论】:

    标签: ios iphone uiview cpu uianimation


    【解决方案1】:

    CPU 达到 100% 几乎总是意味着无限递归。

    我们只能猜测,因为只有 Apple 知道动画源代码中的内容。

    在这种情况下,我猜这可能是由于在动画无法再运行时触发动画造成的(例如,由于我们处于dealloc 状态,所以没有图层)。这意味着完成处理程序被立即调用,这会导致无限递归。

    有更安全的方法来创建无限动画(例如,在图层上使用CAAnimation)。

    【讨论】:

    • 谢谢,这回答了为什么它进入直接循环的问题。我将尝试使用 CAAnimation 或只是我的循环的基本案例。
    • 你猜对了,将NSLog添加到动画完成块中,日志无限输出。
    【解决方案2】:

    你不应该在块边使用 self。它将创建一个保留周期。如果需要调用 self 创建一个弱 self 指针。像这样的代码

    __weak typeof(self) weakself = self;
    [UIView animateWithDuration:4.0
                         delay:1.0
                         options: nil
                         animations:^{ 
                             // Animation PART 1
                             } 
                         completion:^(BOOL  completed){
                           [UIView animateWithDuration:4.0
                               animations:^{ 
                                   // Animation PART 2
                                   } 
                               completion:^(BOOL  completed){
                                 [weakself animateView];
                               }
                             ];
                         }
         ];
    

    但您的代码的主要问题是您在没有任何基本情况的情况下递归调用 animateView。所以我消耗 CPU 周期...不要在没有基本情况的情况下使用 animateView。

    【讨论】:

    • 这似乎是个好主意,但是,我仍然拥有 100% 的 CPU。知道为什么吗?
    • 那个想法是在块中使用 self ... 但实际上你正在递归调用... animateView->animateView->animateView... 这将导致堆栈溢出并使用 CPU 周期...递归只能与基本情况一起使用...基本情况是指您不会再次调用方法的情况...在您的场景中您没有任何基本情况...并且它进入一个循环。
    【解决方案3】:

    尝试使用计时器

    在您的viewDidLoad 或您希望动画开始的任何其他地方写下以下行。

    [NSTimer scheduledTimerWithTimeInterval:9 target:self selector:@selector(animateView) userInfo:nil repeats:YES];
    // 9 is total animation duration.....
    

    按如下方式更新您的 animateView 方法:

    - (void)animateView{
        [UIView animateWithDuration:4.0
                         delay:1.0
                         options: nil
                         animations:^{ 
                             // Animation PART 1
                             } 
                         completion:^(BOOL  completed){
                           [UIView animateWithDuration:4.0
                               animations:^{ 
                                   // Animation PART 2
                                   } 
                               completion:^(BOOL  completed){
    
                               }
                             ];
                         }
         ]; 
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2012-01-13
      相关资源
      最近更新 更多