1

我正在尝试为一些图像设置动画。这些图像在非视网膜 iPad 上运行良好,但它们的视网膜对应物很慢,并且动画不会以指定的速率循环播放。我正在使用的代码如下所示,该方法每 1/25 秒调用一次。这种方法似乎比UIViewAnimations.

if (counter < 285) {
        NSString *file = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Animation HD1.2 png sequence/file_HD1.2_%d", counter] ofType:@"png"];
            @autoreleasepool {
                UIImage *someImage = [UIImage imageWithContentsOfFile:file];
                falling.image = someImage;
            }
        counter ++;
    } else {
        NSLog(@"Timer invalidated");
        [timer invalidate];
        timer = nil;
        counter = 1;
    }
}

我意识到有很多图像,但帧数较少的动画的性能是相同的。就像我说的,非视网膜动画效果很好。上面的每张图片大约是 90KB。我做错了什么还是这仅仅是 iPad 的限制?老实说,当它可以处理复杂的 3D 游戏之类的东西时,我很难相信它无法处理这样的事情,所以我想我做错了什么。任何帮助,将不胜感激。

编辑1:

从下面的答案中,我编辑了我的代码,但无济于事。执行以下代码会导致设备崩溃。

viewDidLoad

NSString *fileName;
myArray = [[NSMutableArray alloc] init];
for(int i = 1; i < 285; i++) {
    fileName = [NSString stringWithFormat:@"Animation HD1.2 png sequence/HD1.2_%d.png", i];
    [myArray addObject:[UIImage imageNamed:fileName]];
    NSLog(@"Loaded image: %d", i);
}
falling.userInteractionEnabled = NO;
falling.animationImages = humptyArray;
falling.animationDuration = 11.3;
falling.animationRepeatCount = 1;
falling.contentMode = UIViewContentModeCenter;

动画方法

-(void) triggerAnimation {
    [falling startAnimating];
}
4

3 回答 3

11

首先,Retina iPad 上的动画性能是出了名的不稳定。也就是说,您可以做一些事情来确保您的动画获得最佳性能(无特定顺序)。

  1. 预加载图像- 正如其他一些人所提到的,当您必须在绘制图像之前等待读取图像时,您的动画速度会受到影响。如果你使用 UIImageView 的动画属性,这个预加载将被自动处理。

  2. 使用正确的图像类型- 尽管文件大小有优势,但使用 JPEG 代替 PNG 会显着降低动画速度。PNG 压缩较少,系统更容易解压缩。此外,Apple 还针对读取和绘制 PNG 图像对 iOS 系统进行了显着优化。

  3. 减少混合- 如果可能,请尝试从动画图像中移除任何透明度。确保图像中没有 Alpha 通道,即使它看起来完全不透明。您可以通过在预览中打开图像并打开检查器来进行验证。通过减少或移除这些透明像素,您可以消除系统在显示图像时必须执行的额外渲染通道。这可以产生重大影响。

  4. 使用 GPU 支持的动画- 不建议您当前使用计时器为图像设置动画的方法以获得最佳性能。通过不使用 UIViewAnimation 或 CAAnimation,您将强制 CPU 完成大部分动画工作。Core Animation 和 UIViewAnimation 的许多动画技术都是由 OpenGL 优化和支持的,它使用 GPU 来处理图像和动画。图形处理是 GPU 的用途,利用它可以最大限度地提高动画性能。

  5. 避免像素错位- 确保动画图像在屏幕上显示时的尺寸正确。如果您在制作动画或使用不正确的帧时拉伸图像,系统必须做更多的工作来处理每一帧。此外,当系统尝试将图像定位在小数像素上时,对任何帧或点值使用整数将避免抗锯齿。

  6. 小心阴影和圆角- CALayer 有很多简单的方法来创建阴影和圆角,但是如果您在动画中移动这些图层,系统通常会在动画的每一帧中重新绘制图层。使用 shadowOffset 属性指定阴影时就是这种情况(使用 UILabel 的阴影属性不会渲染每一帧)。此外,边框和使用 maskToBounds 和 clipToBounds 将更加注重性能,而不仅仅是使用图像编辑器来裁剪实际资产。

于 2012-09-08T00:38:55.983 回答
0

这里有几点需要注意:
如果“下降”是 UIImageView,请确保它的内容模式显示类似“中心”而不是某种缩放(当然,请确保您的图像适合它)。
除此之外,正如@FogleBird 所说,测试您的设备是否有足够的内存来预加载所有图像,如果没有,请尝试至少通过使用图像文件创建 NSData 对象来预加载数据。
您对 @autorelease 池的使用不是很有用,您最终会创建一个自动释放对象,它只做一件事 - 删除对已保留对象的引用 - 没有内存增益,但性能损失。
如果有的话,你应该已经包装了文件名格式化程序代码,并且考虑到这个方法是由 NSTimer 调用的,它已经被包装在一个自动释放池中。

于 2012-09-08T00:12:13.203 回答
0

只是想指出-当您使用图像名称创建 NSString 时-“动画 HD1.2 png 序列/HD1.2_%d.png”是什么?

看起来您正在尝试在那里放置路径,请尝试仅使用图像名称 - 例如。“HD1.2_%d.png”。

于 2012-09-30T15:32:45.870 回答