iOS【完美解決SDWebImage載入多個圖片記憶體崩潰的問題】
阿新 • • 發佈:2018-12-31
SDWebImage大家肯定都恨熟悉了,國內外太多的App使用其進行圖片載入。
但是最近在使用過程中發現,我用SDWebImage載入多個圖片,類似微博動態那種,在載入的過程中。我發現當圖片解析度比較大的時候(不是圖片大),載入幾張圖片就崩潰了。
網上說可以每次載入圖片清空memcache,但是效果並不好。
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
也有說把使用下面這個方法的地方全部注掉
+ (UIImage *)decodedImageWithImage:(UIImage *)image
但是效果並不明顯。同時載入5-7張高解析度圖片還是會立即崩潰
大概是像下面這樣
- NSString *logoString = [_currentDic stringValueForKey:@"team_img"];
- if(logoString.length>0){
- [[SDImageCache sharedImageCache] queryDiskCacheForKey:logoString done:^(UIImage *image, SDImageCacheType cacheType) {
- if
- [_teamImage setImage:image];
- }else{
- [_teamImage sd_setImageWithURL:kNSUrl(logoString)
- placeholderImage:IMGNAMED(@"defaultAvatar2")
- options:SDWebImageRefreshCached
- completed
- if (image) {
- [[SDImageCache sharedImageCache] storeImage:image forKey:logoString toDisk:YES];
- }
- }];
- }
- }];}
在內部都會使用到下面這個方法
- - (UIImage *)diskImageForKey:(NSString *)key {
- NSData *data = [self diskImageDataBySearchingAllPathsForKey:key];
- if (data) {
- UIImage *image = [UIImage sd_imageWithData:data];
- image = [self scaledImageForKey:key image:image];
- image = [UIImage decodedImageWithImage:image];
- return image;
- }
- else {
- return nil;
- }
- }
我發現這裡
- UIImage *image = [UIImage sd_imageWithData:data];
圖片取出來的時候就已經巨大無比,佔用了很大的記憶體,導致記憶體來不及釋放就崩潰。
抽絲剝繭我們進入
- sd_imageWithData方法
發現這裡面對圖片的處理是直接按照原大小進行的,如果幾千是解析度這裡導致佔用了大量記憶體。
所以我們需要在這裡對圖片做一次等比的壓縮。
我們在
UIImage+MultiFormat這個類裡面新增如下壓縮方法,
- +(UIImage *)compressImageWith:(UIImage *)image
- {
- float imageWidth = image.size.width;
- float imageHeight = image.size.height;
- float width = 640;
- float height = image.size.height/(image.size.width/width);
- float widthScale = imageWidth /width;
- float heightScale = imageHeight /height;
- // 建立一個bitmap的context
- // 並把它設定成為當前正在使用的context
- UIGraphicsBeginImageContext(CGSizeMake(width, height));
- if (widthScale > heightScale) {
- [image drawInRect:CGRectMake(0, 0, imageWidth /heightScale , height)];
- }
- else {
- [image drawInRect:CGRectMake(0, 0, width , imageHeight /widthScale)];
- }
- // 從當前context中建立一個改變大小後的圖片
- UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
- // 使當前的context出堆疊
- UIGraphicsEndImageContext();
- return newImage;
- }
- #ifdef SD_WEBP
- elseif ([imageContentType isEqualToString:@"image/webp"])
- {
- image = [UIImage sd_imageWithWebPData:data];
- }
- #endif
- else {
- image = [[UIImage alloc] initWithData:data];
- if (data.length/1024 > 128) {
- image = [self compressImageWith:image];
- }
- UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
- if (orientation != UIImageOrientationUp) {
- image = [UIImage imageWithCGImage:image.CGImage
- scale:image.scale
- orientation:orientation];
- }
UIImage *image = [UIImage sd_imageWithData:self.imageData];
//將等比壓縮過的image在賦在轉成data賦給self.imageData
NSData *data = UIImageJPEGRepresentation(image, 1);
self.imageData = [NSMutableData dataWithData:data];
再配合 [[SDImageCachesharedImageCache] setValue:nilforKey:@"memCache"];(圖片載入後使用)大功告成,親測記憶體基本變化不大,自動釋放也來得及。