现象:tableview滑动到某张图片会变的很卡,然后crash。图片764KB
原因探究:因为测试机无法真机运行,所以在didReceiveMemoryWarning中加alertView给出提示,然后打包上传到服务器,测试机下载包运行,滑倒那张图片那,果然弹出了alertView,说明是内存不足造成的。
最后发现是用SDWebImage加载图片在iPhone4S上出现崩溃。在SDWebImageDownloaderOperation中有- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection代理,在connection成功后处理图片信息。
这中间有UIImage *image = [UIImage sd_imageWithData:self.imageData];从data转化成image。
跟进sd_imageWithData发现在其中用image = [[UIImage alloc] initWithData:data];直接转换,并没有做任何特别处理,正常情况完全没有问题,然而却出现了4S加载700KB图片崩溃的问题,所以我们得做些特别处理。
if(data.length>1024*500){//大于500KB
if(image.size.width>kScreenWidth && image.size.height>kScreenHeight){//长宽都大于屏幕
CGFloat screenScale = kScreenWidth/kScreenHeight;
CGFloat imageScale = image.size.width/image.size.height;
if(imageScale>screenScale){//宽图,长度缩到屏幕高度
image = [image resizeToWidth:image.size.width*kScreenHeight/image.size.height height:kScreenHeight];
}else{//长图,宽度缩到屏幕宽度
image = [image resizeToWidth:kScreenWidth height:image.size.height*kScreenWidth/image.size.width];
}
}
}
- (UIImage *)resizeToWidth:(CGFloat)width height:(CGFloat)height {
CGSize size = CGSizeMake(width, height);
if (UIGraphicsBeginImageContextWithOptions != NULL) {
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
} else {
UIGraphicsBeginImageContext(size);
}
[self drawInRect:CGRectMake(0, 0, width, height)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我们对超过500KB的图片进行长宽压缩处理,然后再渲染到屏幕,结果是可行!当然,图片压缩了,其对应的data就改变了,我们还需要回到-(void)connectionDidFinishLoading:(NSURLConnection *)aConnection
中把imageData更新
//和sd_imageWithData:内部判断逻辑一致,不必什么图片都走下面这步
if(self.imageData.length>1024*500){
if(image.size.width>kScreenWidth && image.size.height>kScreenHeight){
//将等比压缩过的image在赋在转成data赋给self.imageData
NSData *data = UIImageJPEGRepresentation(image, 1);
self.imageData = [NSMutableData dataWithData:data];
}
}
这里依然使用相同的判断逻辑,是为了防止其他小于500KB的图片依然走
NSData *data = UIImageJPEGRepresentation(image, 1);
self.imageData = [NSMutableData dataWithData:data];
这两步,无用功。
更新imageData是必要的,因为SDWebImage中会对图片缓存,imageData会用到。