【问题标题】:CAKeyframeAnimation - Animating an Array of Images creates a huge allocation after completionCAKeyframeAnimation - 对图像数组进行动画处理会在完成后创建一个巨大的分配
【发布时间】:2015-01-12 14:40:26
【问题描述】:

我正在尝试使用CAKeyframeAnimationUIImage 数组设置动画。理论上很简单。
文章底部的示例代码。

我的问题是动画完成后,我有一个无法摆脱的巨大泄漏。

初始化CAKeyframeAnimation的代码:

- (void)animateImages
{
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
    keyframeAnimation.values = self.imagesArray;  // array with images

    keyframeAnimation.repeatCount = 1.0f;
    keyframeAnimation.duration = 5.0;

    keyframeAnimation.removedOnCompletion = YES;

    CALayer *layer = self.animationImageView.layer;

    [layer addAnimation:keyframeAnimation
             forKey:@"flingAnimation"];
}

在动画中添加代理和手动移除动画会导致相同的泄漏效果:

... // Code to change

keyframeAnimation.delegate = self;

//    keyframeAnimation.removedOnCompletion = YES;
keyframeAnimation.removedOnCompletion = NO;
keyframeAnimation.fillMode = kCAFillModeForwards;

....

然后:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    if (flag)
    {
        [self.animationImageView.layer removeAllAnimations];
        [self.animationImageView.layer removeAnimationForKey:@"flingAnimation"]; // just in case
    }
}

结果总是一个巨大的分配。内存堆栈的大小与图像的大小成正比:

I uploaded an example to GitHub to check the code.

【问题讨论】:

  • 我运行仪器,没有泄漏,但分配很高。
  • 你知道如何解决高分配吗?
  • 改用imageWithContentsOfFile
  • 动画完成后,只需将图像数组设置为 nil。
  • 这不起作用。这是我尝试的第一件事

标签: ios objective-c xcode uiimage cakeyframeanimation


【解决方案1】:

已解决

我发现了问题。

正如gabbler 所说,没有泄漏问题。问题是图像的高分配。

我正在释放包含图像的数组,但是图像并没有从内存中消失。

所以我终于找到了问题:

    [UIImage imageNamed:@""];

从方法定义:

This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method locates and loads the image data from disk or asset catelog, and then returns the resulting object. You can not assume that this method is thread safe.

所以,imageNamed: 将图像存储在私有缓存中。
- 第一个问题是您无法控制缓存大小。
- 第二个问题是缓存没有被及时清理,如果你用imageNamed:分配了很多图片,你的应用很可能会崩溃。

解决方案

直接从Bundle分配图片:

NSString *imageName = [NSString stringWithFormat:@"imageName.png"];
NSString *path = [[NSBundle mainBundle] pathForResource:imageName

// Allocating images with imageWithContentsOfFile makes images to do not cache.
UIImage *image = [UIImage imageWithContentsOfFile:path];

小问题

Images.xcassets 中的图像永远不会被分配。所以,把你的图片移到 Images.xcassets 之外,直接从 Bundle 中分配。

Example project with solution here.

【讨论】:

  • 添加 300 张图片,您的解决方案也将不起作用:D
  • 但是我不能使用视频,因为我需要在 AVMutableVideoComposition 的帮助下通过添加 CALayer 并放置 CAKeyframeAnimation 将图像放在视频上。 (因为使用视频不会像 PNG 图像那样具有 alpha)。如果我必须在 UI 上显示动画,您对使用视频的建议很好,但在我的情况下,我还需要将动画保存在 Video 上。提前感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多