CAKeyframeAnimation - 动画图像数组在完成后创建一个巨大的分配
CAKeyframeAnimation - Animating an Array of Images creates a huge allocation after completion
我正在尝试使用 CAKeyframeAnimation
对 UIImage
的数组进行动画处理。理论上很简单。
底部的示例代码 post.
我的问题是动画完成后,我有一个巨大的泄漏,无法消除它。
初始化代码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
}
}
结果总是一个巨大的分配。内存堆栈的大小与图像的大小成正比:
已解决
我发现了问题。
正如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 分配。
我正在尝试使用 CAKeyframeAnimation
对 UIImage
的数组进行动画处理。理论上很简单。
底部的示例代码 post.
我的问题是动画完成后,我有一个巨大的泄漏,无法消除它。
初始化代码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
}
}
结果总是一个巨大的分配。内存堆栈的大小与图像的大小成正比:
已解决
我发现了问题。
正如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 分配。