iOS优化

关于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

上一篇 下一篇

猜你喜欢

热点阅读