解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题
本文轉(zhuǎn)載至?http://www.superqq.com/blog/2015/01/22/jie-jue-mwphotobrowserzhong-de-sdwebimagejia-zai-da-tu-dao-zhi-de-nei-cun-jing-gao-wen-ti/
MWPhotoBrowser是一個(gè)非常不錯(cuò)的照片瀏覽器,在github的star接近3000個(gè),MWPhotoBrowser下載
MWPhotoBrowser來(lái)加載小圖1M以下的都應(yīng)該不會(huì)有內(nèi)存警告的問(wèn)題。如果遇到大圖,3M、4M、5M的大圖,很有可能導(dǎo)致內(nèi)存警告。最近我就遇到這個(gè)問(wèn)題,很是頭疼。來(lái)回滑動(dòng)查看照片內(nèi)存飆到100M以上:
?
網(wǎng)上查了很多資料,都沒(méi)有解決問(wèn)題。
我們來(lái)看一下MWPhotoBrowser,其實(shí)MWPhotoBrowser用的是SDWebImage來(lái)下載圖片的。SDWebImage下載
在github看到SDWebImage的介紹,后面說(shuō)到:
Future Enhancements
?
? ? LRU memory cache cleanup instead of reset on memory warning
看到這個(gè)真是欲哭無(wú)淚啊。
再去看看SDWebImage的,有個(gè)人提問(wèn)了:
How to disable "memory cache"?? I don't want memory cache,? it used a lot of memory and got memory waring easily,? disk is enough for me...
有人回答:
There is no way to disable the memory cache. But the cache is designed to flush itself when you get a memory warning, so you shouldn't need to worry it.
說(shuō)的是SDWebImage遇到內(nèi)存警告會(huì)自動(dòng)釋放內(nèi)存,但是這還是解決不了問(wèn)題,加載大圖的時(shí)候,內(nèi)存會(huì)突然蹦到100多M,在4s及以下的手機(jī)上跑,再就掛了。
還是沒(méi)有解決內(nèi)存警告的問(wèn)題。怎么辦呢?
我是這么解決的:
SDWebImage有一個(gè)SDWebImageDownloaderOperation類來(lái)執(zhí)行下載操作的。里面有個(gè)下載完成的方法:
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
?? SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock;
?? @synchronized(self) {
?? ? ? CFRunLoopStop(CFRunLoopGetCurrent());
?? ? ? self.thread = nil;
?? ? ? self.connection = nil;
?? ? ? [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:nil];
?? }
?
?? if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) {
?? ? ? responseFromCached = NO;
?? }
?
?? if (completionBlock)
?? {
?? ? ? if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
?? ? ? ? ? completionBlock(nil, nil, nil, YES);
?? ? ? }
?? ? ? else {
?? ? ? ? ? UIImage *image = [UIImage sd_imageWithData:self.imageData];
?? ? ? ? ? NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
?? ? ? ? ? image = [self scaledImageForKey:key image:image];
?
?? ? ? ? ? // Do not force decoding animated GIFs
?? ? ? ? ? if (!image.images) {
?? ? ? ? ? ? ? image = [UIImage decodedImageWithImage:image];
?? ? ? ? ? }
?? ? ? ? ? if (CGSizeEqualToSize(image.size, CGSizeZero)) {
?? ? ? ? ? ? ? completionBlock(nil, nil, [NSError errorWithDomain:@"SDWebImageErrorDomain" code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
?? ? ? ? ? }
?? ? ? ? ? else {
?? ? ? ? ? ? ? completionBlock(image, self.imageData, nil, YES);
?? ? ? ? ? }
?? ? ? }
?? }
?? self.completionBlock = nil;
?? [self done];
}
其中,UIImage *image = [UIImage sd_imageWithData:self.imageData];就是將data轉(zhuǎn)換成image。
再看看sd_imageWithData:這個(gè)方法:
+ (UIImage *)sd_imageWithData:(NSData *)data {
?? UIImage *image;
?? NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
?? if ([imageContentType isEqualToString:@"image/gif"]) {
?? ? ? image = [UIImage sd_animatedGIFWithData:data];
?? }
#ifdef SD_WEBP
?? else if ([imageContentType isEqualToString:@"image/webp"])
?? {
?? ? ? image = [UIImage sd_imageWithWebPData:data];
?? }
#endif
?? else {
?? ? ? image = [[UIImage alloc] initWithData:data];
?? ? ? UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
?? ? ? if (orientation != UIImageOrientationUp) {
?? ? ? ? ? image = [UIImage imageWithCGImage:image.CGImage
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? scale:image.scale
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? orientation:orientation];
?? ? ? }
?? }
?
?
?? return image;
}
這個(gè)方法在UIImage+MultiFormat里面,是UIImage的一個(gè)類別處理。這句話很重要image = [[UIImage alloc] initWithData:data]; SDWebImage把下載下來(lái)的data直接轉(zhuǎn)成image,然后沒(méi)做等比縮放直接存起來(lái)使用。所以,我們只需要在這邊做處理即可:
UIImage+MultiFormat添加一個(gè)方法:
+(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;
?
?? // 創(chuàng)建一個(gè)bitmap的context
?? // 并把它設(shè)置成為當(dāng)前正在使用的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)];
?? }
?
?? // 從當(dāng)前context中創(chuàng)建一個(gè)改變大小后的圖片
?? UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
?? // 使當(dāng)前的context出堆棧
?? UIGraphicsEndImageContext();
?
?? return newImage;
?
}
然后在:image = [[UIImage alloc] initWithData:data];下面調(diào)用以下:
if (data.length/1024 > 1024) {
?? ? ? ? ? image = [self compressImageWith:image];
?? ? ? }
當(dāng)data大于1M的時(shí)候做壓縮處理。革命尚未成功,還需要一步處理。在SDWebImageDownloaderOperation的connectionDidFinishLoading方法里面的:
? UIImage *image = [UIImage sd_imageWithData:self.imageData];
?
? //將等比壓縮過(guò)的image在賦在轉(zhuǎn)成data賦給self.imageData
? NSData *data = UIImageJPEGRepresentation(image, 1);
? self.imageData =? [NSMutableData dataWithData:data];
大工告成,我們來(lái)看一下效果吧:
?
果然問(wèn)題得以解決。
更多iOS開發(fā)相關(guān)技術(shù)請(qǐng)關(guān)注iOS開發(fā)微信公眾號(hào) iOS開發(fā) :
iOSDevTip
Posted by 李剛 Jan 22nd, 2015 11:23 am ios開發(fā)
本文出處剛剛在線:http://www.superqq.com/blog/2015/01/22/jie-jue-mwphotobrowserzhong-de-sdwebimagejia-zai-da-tu-dao-zhi-de-nei-cun-jing-gao-wen-ti/
?
自由轉(zhuǎn)載-請(qǐng)?jiān)陂_頭注明本文出處。
轉(zhuǎn)載于:https://www.cnblogs.com/Camier-myNiuer/p/5100721.html
總結(jié)
以上是生活随笔為你收集整理的解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: gulp build
- 下一篇: 1.3.3 改善后的异常处理