2

大家好,小问题。

我有一个UIView我创建的类,AnimatedUIView. 在 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,这并没有真正得到回答。非常感谢!

4

3 回答 3

5

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

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

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

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

于 2013-11-12T12:07:05.993 回答
3

您不应该在块中使用 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。

于 2013-11-12T09:20:50.390 回答
1

尝试使用计时器

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){

                           }
                         ];
                     }
     ]; 

}
于 2013-11-12T09:19:16.660 回答