我的 UIView 动画很生涩 - 如何优化以下代码?

Posted

技术标签:

【中文标题】我的 UIView 动画很生涩 - 如何优化以下代码?【英文标题】:My UIView animation is jerky - how can I optimize the following code? 【发布时间】:2012-01-14 01:22:25 【问题描述】:

在模拟器上,我的动画方法运行流畅。不幸的是,它在 iPhone 4 上运行似乎非常生涩。

我不能 100% 确定制作动画的最佳和最快方法 - 因此,如果我能优化或完全修改我的代码以加快动画速度,我将不胜感激!

注意事项:

它已经在主线程上,所以这是否会使 'dispatch_async(dispatch_get_main_queue())' 调用无关或无用?

有没有办法预先缓冲这个动画?

有没有办法准确地查看代码的哪一部分造成了大部分的减速?

extensionView.subviews 中只有大约 3 或 4 个视图。

我用 -Os 编译过。

- (void)extendWithAnimation:(BOOL)animated; 

    isExtended = YES;
    extensionView.hidden = NO;
    topShadowView.hidden = NO;

    topShadowView.frame = CGRectMake(0, defaultHeight, topShadowView.frame.size.width, topShadowView.frame.size.height);
    topShadowView.layer.bounds = CGRectMake(0, 0, topShadowView.frame.size.width, 0);
    extensionView.frame = CGRectMake(0, defaultHeight - 8, DEVICE_WIDTH, extensionHeight + 8);
    extensionView.layer.bounds = CGRectMake(0, 0, DEVICE_WIDTH, 0);

    for (UIView *view in extensionView.subviews) 
        view.transform = CGAffineTransformMakeTranslation(0, -(extensionHeight+8));
    

    dispatch_async(dispatch_get_main_queue(), ^

        if (animated) 
            [UIView beginAnimations:nil context:nil];
            [UIView setAnimationDuration:0.3];
            [UIView setAnimationDelegate:self];
        

        extensionView.layer.bounds = CGRectMake(0, 0, DEVICE_WIDTH, extensionHeight + 8);
        topShadowView.layer.bounds = CGRectMake(0, 0, topShadowView.frame.size.width, extensionHeight + 8);

        for (UIView *view in extensionView.subviews) 
            view.transform = CGAffineTransformIdentity;
        

        if (animated) 
            [UIView commitAnimations];
        
    );   

解决方案:

已解决(感谢 Aaron!)。

渲染的阴影会扼杀动画!如果您打算制作动画,请不要使用任何核心图形阴影属性 - 在我的例子中,只有几个阴影将帧速率降低了三倍。

【问题讨论】:

CALayer 阴影绘制性能如果为​​图层指定 shadowPath 会大大提高,您可以在删除所有代码之前尝试一下... @jrturton 很有趣,不幸的是,这对于我的问题所在的 UITextView 并不起作用。但对于其他有类似问题的人来说,这听起来很不错! 【参考方案1】:
    好吧,如果代码已经在主队列中,那么使用 dispatch_async 只会产生开销。 我不知道这是否会有所帮助(我有点怀疑),但您可以尝试使用[UIView animateWithDuration:.3 animations: code... ]; 在我过去尝试处理阴影时,它们往往会对性能造成很大影响。您可能会考虑单独保留阴影和图层,而是创建一个可调整大小的阴影 PNG,您可以在 UIImageView 中使用它,该 UIImageView 放置在您想要阴影的视图后面。

【讨论】:

谢谢!阴影视图实际上是您建议的 PNG,尽管一些涉及的子视图已经渲染了阴影,所以也许这就是问题所在 - 将很快尝试 :) 我同意 dispatch_async() 是不必要的,但是 GCD 真的非常快;如果这会增加任何有意义的延迟,我会感到惊讶。 @Jordan 可能,我首先要移除阴影,看看它的表现如何。如果是这样,那么您可以将它们重新添加为 PNG,然后重试。 我也同意 GCD 速度很快,性能损失应该可以忽略不计。 GCD 可能不会增加延迟,但绝对没有意义。它所做的只是将动画从开始延迟 1/60 秒。你不能在后台线程上做 UIView 动画,你不应该尝试。【参考方案2】:

通过 Instruments 运行您的代码(从 Time Profiler 开始)。动画期间哪些调用占用的时间最多?

一旦您对其进行了分析,还可以通过 Core Animation 工具运行它,并启用屏幕外渲染和非透明内容的着色。这将有助于隔离常见的图形问题。

我还注意到你提到了阴影。如果您使用的是 CALayer 阴影属性,那可能会影响您的性能。但我们需要更多信息才能真正确定这一点。

【讨论】:

以上是关于我的 UIView 动画很生涩 - 如何优化以下代码?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery中的生涩动画问题

使用 SharpDX 在 WPF 中滚动图像时出现生涩动画

自动布局中断 UIView 动画

使用 CADisplayLink 的 iOS OpenGL ES 1.1 生涩动画(重启修复了一段时间)

如何制作流畅的 UIView 分割动画?

如何创建自定义 UIView 动画