当前位置: 代码迷 >> 综合 >> iPhoneSE列表加载图片crash的解决方案
  详细解决方案

iPhoneSE列表加载图片crash的解决方案

热度:14   发布时间:2024-02-22 04:17:08.0

        近期业务做了评论模块,评论内容跟其他APP基本一致,就是评分、文字以及图片,每条评论可以至多包含6张图片,在评论列表会展示评论星级、用户头像、昵称、评论文字、图片以及评论时间,逻辑非常简单,一天搞完,提交打包给测试验证,基本无有效bug,第二天下午测试跑过来说在iPhoneSE上有一个商品,点击后滑动就必会crash,我开始以为是图片数组越界导致,但是测试说别的手机不会crash,我去bugly查看crash信息,发现bugly空空如也,并无crash上报,无奈之下只有真机debug了,找到对应商品,点击进详情页然后滑动,果然crash了,但是xcode并未捕捉到crash堆栈,猜测是内存问题,于是在didreceivememeryWarning方法出断点,再次启动,重新操作,不出意外,crash了,但是还是未走到断点处,最后,打开所有的异常断点,再次启动测试,这次捕捉到了,是sdwebimage 代码在解压图片的时候内存申请失败,在console也出现了terminate due to memery issue,原因找到了怎么解决呢?于是开始以下尝试:

  1. 是否是SE内存太小,SD内存cache太多导致?于是设置SDCache最多为6张(一条评论数据的图片),然后重新启动,验证,依然crash。
  2. 是否是内存峰值过高导致?于是在每条cell更新的时候加上了autoreleasepool,接着启动,测试,crash继续。
  3. 是否是某张图片太大导致?于是把每张图片都download下来,查看图片大小,但是没有发现某张图片dataSize非常大,但总算有结果了,原来每张图片大小有500k,终端上传的时候做了500k的上限限制,于是想着裁剪图片。
  4. 最后网络上找到了WWDC针对大图片优化的最佳实践,就是下采样,主要代码如下
    CGImageSourceRef source =  CGImageSourceCreateWithURL((__bridge CFURLRef)url, nil);CFDictionaryRef options = (__bridge CFDictionaryRef) @{(id) kCGImageSourceCreateThumbnailWithTransform : @YES,(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,(id) kCGImageSourceThumbnailMaxPixelSize : @(60*[UIScreen mainScreen].scale)};CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, options);UIImage *scaled = [UIImage imageWithCGImage:scaledImageRef];CGImageRelease(scaledImageRef);

 创建缩略图以后,再次验证,crash问题没有了,但是出现了别的问题,cell滚动后重新加载会显示placeholder,然后再显示图片,这是没有加缓存的问题,于是,运用SDImagecache给缩略图加上缓存,再次运行,完美解决。

@interface ThumbImageManager : NSObject+ (instancetype)sharedManager;
- (void)thumbImageWithUrl:(NSString *)urlString width:(float)widthblock:(void(^)(NSString *url,UIImage *image))callBack;
@end
#import "ThumbImageManager.h"@interface ThumbImageManager ()@property(nonatomic,strong)NSOperationQueue *queue;@end@implementation ThumbImageManager+ (instancetype)sharedManager{static ThumbImageManager *manager = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[ThumbImageManager alloc] init];});return manager;
}
- (instancetype)init{self = [super init];if (self) {_queue = [[NSOperationQueue alloc] init];_queue.maxConcurrentOperationCount = 6;}return self;;
}
- (void)thumbImageWithUrl:(NSString *)urlString width:(float)width block:(void(^)(NSString *url,UIImage *image))callBack{NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{NSString *path = [[urlString md5String] stringByAppendingString:@"thumb"];UIImage *image =  [[SDImageCache sharedImageCache] imageFromCacheForKey:path];if (image) {callBack(urlString,image);}else{NSURL *url = [NSURL URLWithString:urlString];CGImageSourceRef source =  CGImageSourceCreateWithURL((__bridge CFURLRef)url, nil);CFDictionaryRef options = (__bridge CFDictionaryRef) @{(id) kCGImageSourceCreateThumbnailWithTransform : @YES,(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,(id) kCGImageSourceThumbnailMaxPixelSize : @(width*[UIScreen mainScreen].scale),(id) kCGImageSourceCreateThumbnailWithTransform:@YES};CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, options);UIImage *scaled = [UIImage imageWithCGImage:scaledImageRef];CGImageRelease(scaledImageRef);[[SDImageCache sharedImageCache] storeImage:scaled forKey:path completion:nil];callBack(urlString,scaled);}}];[_queue addOperation:op];
}
@end

 

 

  相关解决方案