关于SDWebImage加载gif动图导致内存爆炸的那些事
2021-08-13 本文已影响0人
crazyfox
关于SDWebImage加载gif动图导致内存爆炸的那些事
SD加载gif比较方便,但是如果在列表这种滚动试图中有多张gif,会导致内存爆炸
源码的SDImageGIFCoder.m文件中,在解码图片这一步
- (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderOptions *)options {
······
BOOL decodeFirstFrame = [options[SDImageCoderDecodeFirstFrameOnly] boolValue];
if (decodeFirstFrame || count <= 1) {
animatedImage = [[UIImage alloc] initWithData:data scale:scale];
} else {
NSMutableArray<SDImageFrame *> *frames = [NSMutableArray array];
for (size_t i = 0; i < count; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!imageRef) {
continue;
}
float duration = [self sd_frameDurationAtIndex:i source:source];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
CGImageRelease(imageRef);
SDImageFrame *frame = [SDImageFrame frameWithImage:image duration:duration];
[frames addObject:frame];
}
NSUInteger loopCount = [self sd_imageLoopCountWithSource:source];
animatedImage = [SDImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
}
animatedImage.sd_imageFormat = SDImageFormatGIF;
CFRelease(source);
return animatedImage;
#endif
}
frames数组中添加了多张UIImage,而且保存在memory中,不会主动释放,所以会有问题
解决方案1:修改源码
SDImageCache.m文件中,
- (void)storeImage:(nullable UIImage *)image
imageData:(nullable NSData *)imageData
forKey:(nullable NSString *)key
toMemory:(BOOL)toMemory
toDisk:(BOOL)toDisk
completion:(nullable SDWebImageNoParamsBlock)completionBlock {
······
//添加判断,如果是gif就不存memory,而存disk
if (toMemory && self.config.shouldCacheImagesInMemory && ![[key lowercaseString] containsString:@".gif"]) {
NSUInteger cost = image.sd_memoryCost;
[self.memoryCache setObject:image forKey:key cost:cost];
}
if (toDisk || [[key lowercaseString] containsString:@".gif"]) {
dispatch_async(self.ioQueue, ^{
//添加判断,如果是gif就不存memory,而存disk,这样减少内存消耗
解决方案2:业务逻辑中,使用YYAnimatedImageView加载gif图片
if([url.lastPathComponent containsString:@".gif"]){
YYAnimatedImageView *yyimageview;
UIView *view = [imageView viewWithTag:10001];
if(!view){
yyimageview=[[YYAnimatedImageView alloc]initWithFrame:imageView.bounds];
yyimageview.tag = 10001;
[imageView addSubview:yyimageview];
}
yyimageview.imageURL = url;
}else{
可以显著降低内存消耗
over