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;
}
添加完毕,再来看看内存,明显感觉内存使用小很多了,解决完毕。
网友评论