美文网首页
SDWebImage加载多个大图导致内存泄漏崩溃

SDWebImage加载多个大图导致内存泄漏崩溃

作者: 远航Yang | 来源:发表于2017-10-16 09:11 被阅读0次

    SDWebImage是iOS开发者加载网络图片比较常用的开源框架,高效的缓存机制,加载根据缓存取出相对应图片解压展示,使用户用起来是非常顺畅的。但是我在做图片轮播的时候,遇到了用户上传了多张大图的时候,大概每张小于1M的,我连续加载几个相同的页面,我看到XCode的使用内存从20M飙升到500M,接着didReceiveMemoryWarning断点了,内存泄漏,接着程序奔溃了。由于之前一直听说SDWebImage加载大图会奔溃的问题,所以这次遇到,我直接找SDWebImage的问题的。

    1、直接在UIImage+MultiFormat添加图片压缩方法,根据屏幕比例,分辨率来压缩图片

    +(UIImage*)compressImageWith:(UIImage*)image

    {

    floatimageWidth = image.size.width;

    floatimageHeight = image.size.height;

    floatwidth =640;

    floatheight = image.size.height/(image.size.width/width);

    floatwidthScale = imageWidth /width;

    floatheightScale = imageHeight /height;

    // 创建一个bitmap的context

    // 并把它设置成为当前正在使用的context

    if([[UIScreenmainScreen]scale] ==2.0){

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height),NO,2.0);

    }elseif([[UIScreenmainScreen]scale] ==3.0){

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height),NO,3.0);

    }

    else{

    UIGraphicsBeginImageContext(CGSizeMake(width, height));

    }

    if(widthScale > heightScale) {

    [imagedrawInRect:CGRectMake(0,0, imageWidth /heightScale , height)];

    }

    else{

    [imagedrawInRect:CGRectMake(0,0, width , imageHeight /widthScale)];

    }

    // 从当前context中创建一个改变大小后的图片

    UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

    // 使当前的context出堆栈

    UIGraphicsEndImageContext();

    returnnewImage;

    }

    2、在UIImage+MultiFormat原有的方法sd_imageWithData中调用compressImageWith方法

    + (UIImage*)sd_imageWithData:(NSData*)data {

    if(!data) {

    returnnil;

    }

    UIImage*image;

    NSString*imageContentType = [NSDatasd_contentTypeForImageData:data];

    if([imageContentTypeisEqualToString:@"image/gif"]) {

    image = [UIImagesd_animatedGIFWithData:data];

    }

    #ifdef SD_WEBP

    elseif([imageContentType isEqualToString:@"image/webp"])

    {

    image = [UIImage sd_imageWithWebPData:data];

    }

    #endif

    else{

    image = [[UIImagealloc]initWithData:data];

    if(data.length/1024>128) {

    image = [selfcompressImageWith:image];

    }

    UIImageOrientationorientation = [selfsd_imageOrientationFromImageData:data];

    if(orientation !=UIImageOrientationUp) {

    image = [UIImageimageWithCGImage:image.CGImage

    scale:image.scale

    orientation:orientation];

    }

    }

    returnimage;

    }

    3、最后一步,在SDWebImageDownloaderOperation的connectionDidFinishLoading添加根据判断图片类型进行压缩

    if(self.options&SDWebImageDownloaderIgnoreCachedResponse&&responseFromCached) {

    completionBlock(nil,nil,nil,YES);

    }elseif(self.imageData) {

    UIImage*image = [UIImagesd_imageWithData:self.imageData];

    NSString*key = [[SDWebImageManagersharedManager]cacheKeyForURL:self.request.URL];

    image = [selfscaledImageForKey:keyimage:image];

    //自己添加

    NSPUIImageTypeimageType =NSPUIImageTypeFromData(self.imageData);

    if(imageType ==NSPUIImageType_PNG) {

    NSData*data =UIImagePNGRepresentation(image);

    self.imageData= [NSMutableDatadataWithData:data];

    }elseif(imageType ==NSPUIImageType_JPEG) {

    NSData*data =UIImageJPEGRepresentation(image,1);

    self.imageData= [NSMutableDatadataWithData:data];

    }

    //判断图片格式内联方法

    /*

    typedef NS_ENUM(NSInteger, NSPUIImageType) {

    NSPUIImageType_JPEG,

    NSPUIImageType_PNG,

    NSPUIImageType_Unknown

    };*/

    staticinlineNSPUIImageTypeNSPUIImageTypeFromData(NSData*imageData)

    {

    if(imageData.length>4) {

    constunsignedchar*bytes = [imageDatabytes];

    if(bytes[0] ==0xff&&

    bytes[1] ==0xd8&&

    bytes[2] ==0xff)

    {

    returnNSPUIImageType_JPEG;

    }

    if(bytes[0] ==0x89&&

    bytes[1] ==0x50&&

    bytes[2] ==0x4e&&

    bytes[3] ==0x47)

    {

    returnNSPUIImageType_PNG;

    }

    }

    returnNSPUIImageType_Unknown;

    }

    添加完毕,再来看看内存,明显感觉内存使用小很多了,解决完毕。

    相关文章

      网友评论

          本文标题:SDWebImage加载多个大图导致内存泄漏崩溃

          本文链接:https://www.haomeiwen.com/subject/nlahuxtx.html