使用 SDWebImage 加载大 gif 导致 iOS 应用崩溃并出现内存错误
Loading a big gif with SDWebImage caused iOS app crash with memory error
我正在使用 SDWebImage 框架从 UIImageView
中的 UIImageView
中从互联网返回的 url 获取全屏图像,如下所示:
[imageView sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"placeholder"] options:SDWebImageCacheMemoryOnly completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (!error) {
//added as subview
} else {
//show error
}
}];
当图像的格式为jpg
或png
时,显示效果很好,甚至是一些正常大小的gif
。但是当gif
很大的时候,会导致崩溃,XCode报这样的错误:
Message from debugger: Terminated due to Memory Error
更新: 每次导致崩溃的 gif
图像是 299px
*299px
和 570KB
大。对于那些有兴趣看 gif 的人,link 是:
http://ww4.sinaimg.cn/large/604e48d0jw1evcn03adjjg208b08bdv0.gif
每次单击预览缩略图时,我都可以重新创建它。
我该如何解决这个问题?使用什么工具来观察根本原因?我做了一些研究,我想这是否是因为我使用了选项 SDWebImageCacheMemoryOnly
,而大 gif 占用了我应用程序的大部分内存,所以它崩溃了。谢谢。
关于您的 gif 动画图像,我注意到它非常长(根据 帧数 )动画 - 3191 帧。这些帧中的每一帧都是 300x300,总共将近 300 百万 像素。而且我们必须一次将所有这些像素保存在内存中:没有其他方法可以快速显示帧。而且好像编码成RGB,所以每个像素都是4字节。如果我是对的,那么显示这个东西需要超过 1 GB 的内存。这当然是 Graphic Converter 所建议的:
所以你是对的,我完全可以想象显示这个可能会很麻烦。我的建议是:不要。
SDWebImage 有自己的 GIF 支持实现。问题是他们迭代所有帧并预先创建位图:
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
duration += [self sd_frameDurationAtIndex:i source:source];
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CGImageRelease(image);
}
另一方面,FLAnimatedImage 按需创建位图并智能地缓存它们。
看看FLAnimatedImage. And image loaders that use it for GIF playback like Nuke (mine), PINRemoteImage、FLAnimatedImage_AFNetworking等,或者直接用FLAnimatedImage
我正在使用 SDWebImage 框架从 UIImageView
中的 UIImageView
中从互联网返回的 url 获取全屏图像,如下所示:
[imageView sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"placeholder"] options:SDWebImageCacheMemoryOnly completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (!error) {
//added as subview
} else {
//show error
}
}];
当图像的格式为jpg
或png
时,显示效果很好,甚至是一些正常大小的gif
。但是当gif
很大的时候,会导致崩溃,XCode报这样的错误:
Message from debugger: Terminated due to Memory Error
更新: 每次导致崩溃的 gif
图像是 299px
*299px
和 570KB
大。对于那些有兴趣看 gif 的人,link 是:
http://ww4.sinaimg.cn/large/604e48d0jw1evcn03adjjg208b08bdv0.gif
每次单击预览缩略图时,我都可以重新创建它。
我该如何解决这个问题?使用什么工具来观察根本原因?我做了一些研究,我想这是否是因为我使用了选项 SDWebImageCacheMemoryOnly
,而大 gif 占用了我应用程序的大部分内存,所以它崩溃了。谢谢。
关于您的 gif 动画图像,我注意到它非常长(根据 帧数 )动画 - 3191 帧。这些帧中的每一帧都是 300x300,总共将近 300 百万 像素。而且我们必须一次将所有这些像素保存在内存中:没有其他方法可以快速显示帧。而且好像编码成RGB,所以每个像素都是4字节。如果我是对的,那么显示这个东西需要超过 1 GB 的内存。这当然是 Graphic Converter 所建议的:
所以你是对的,我完全可以想象显示这个可能会很麻烦。我的建议是:不要。
SDWebImage 有自己的 GIF 支持实现。问题是他们迭代所有帧并预先创建位图:
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
duration += [self sd_frameDurationAtIndex:i source:source];
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CGImageRelease(image);
}
另一方面,FLAnimatedImage 按需创建位图并智能地缓存它们。
看看FLAnimatedImage. And image loaders that use it for GIF playback like Nuke (mine), PINRemoteImage、FLAnimatedImage_AFNetworking等,或者直接用FLAnimatedImage