为什么用CGImageSource加载gif会导致内存泄漏?

时间:2016-05-06 13:55:49

标签: ios objective-c

我的项目中有一个gif文件。我想在我的UIImageView中显示该gif文件。这是我的代码:

NSData* gifOriginalImageData = [NSData dataWithContentsOfURL:url];// url of the gif file
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)gifOriginalImageData, NULL);

NSMutableArray *arr = [[NSMutableArray alloc] init];

NSInteger imagesCountInGifFile = CGImageSourceGetCount(src);
CGImageRef imagesOut[imagesCountInGifFile];
for (int i = 0; i < imagesCountInGifFile; ++i) {
    [arr addObject:[UIImage imageWithCGImage:CGImageSourceCreateImageAtIndex(src, i, NULL)]];
}

self.onboardingImageView.animationImages = arr;
self.onboardingImageView.animationDuration = 1.5;
self.onboardingImageView.animationRepeatCount = 2;
[self.onboardingImageView startAnimating];

我可以使用此代码成功显示gif文件。但是,它会导致内存泄漏高达250mb,有60张图像。我试图用给定的代码减少内存,但是没有再次成功。

self.onboardingImageView.animationImages = nil;
CFRelease(src);

任何帮助将不胜感激。 编辑:我添加了一个潜在泄漏的image

2 个答案:

答案 0 :(得分:4)

如果某个函数中包含单词Create,则表示您负责释放它返回的内容。在这种情况下,CGImageSourceCreateImageAtIndex的{​​{3}}明确表示:

  

返回CGImage对象。您负责使用CGImageRelease释放此对象。

您反复调用CGImageSourceCreateImageAtIndex,但实际上从未释放它返回的CGImage,因此导致内存泄漏。一般的经验法则是每次调用一个包含单词Create的函数 - 你应该有一个等效的版本。

我也没有看到你的CGImages数组的重点(当你创建一个UIImages数组时)。这意味着您所要做的就是在循环的每次迭代中创建CGImage,将其包装在UIImage中,将此图像添加到数组中,然后最终释放CGImage。例如:

CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)gifOriginalImageData, NULL);

NSMutableArray *arr = [[NSMutableArray alloc] init];

NSInteger imagesCountInGifFile = CGImageSourceGetCount(src);
for (int i = 0; i < imagesCountInGifFile; ++i) {
    CGImageRef c = CGImageSourceCreateImageAtIndex(src, i, NULL); // create the CGImage
    [arr addObject:[UIImage imageWithCGImage:c]]; // wrap that CGImage in a UIImage, then add to array
    CGImageRelease(c); // release the CGImage <- This part is what you're missing!
}

CFRelease(src); // release the original image source

请注意,您还应该桥接gifOriginalImageData而不是投射(我假设您正在使用ARC)。

通过更改,上面的代码运行正常,没有任何内存泄漏。

答案 1 :(得分:0)

你想要使用NSData数组和UIImage数组。默认情况下压缩图像数据,使用UIImage解压缩数据。

另外,UIImage在内存中有一些缓存,内存很难。

Michael Behan撰写了一篇关于该主题的精彩博文:http://mbehan.com/post/78399605333/uiimageview-animation-but-less-crashy

他写了一个有用的图书馆(麻省理工学院许可证)以防止这种情况发生:https://github.com/mbehan/animation-view