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;
}
添加完畢,再來看看內存,明顯感覺內存使用小很多了,解決完畢。