最近发现应用有卡顿现象,后来仔细查找,发现有几个地方是挺耗内存的。
1.应用中使用了地图,页面返回的时候,地图缓存没有清理
2.网络请求,页面返回的时候没有终止网络加载任务
3.加载的h5页面,没有进行缓存,着实体验不佳,每次都要加载
4.dealloc方法,为什么没有执行?
5.app中怎样减少loading,达到更顺畅的体验
针对以上问题,进行了一系列的检索,实验,不过庆幸的是,差不多一天的时间,把这些问题都解决了,现做一下整理。
解决问题1.应用中使用了地图,页面返回的时候,地图缓存没有清理
应用中使用了地图,页面返回的时候,地图缓存没有清理,项目中集成了苹果地图,发现每次打开地图界面,内存都会上升几十M,并且一直上升不降,直到卡死,造成这一结果的根本原因是地图的mapView没有释放,导致每次打开地图界面的时候内存中都重新加载了一个地图mapView。于是在网上搜索了一番找到了解决办法,只需要在地图的ViewController中dealloc方法中释放掉mapView,将mapView设置成nil就行了。详见博客地址:http://blog.csdn.net/isalvador/article/details/51082860,具体代码如下:
//并且在界面将要显示的时候设置代理,将要消失的时候取消代理
- (void)viewWillAppear:(BOOL)animated {
_mapView.delegate = self;
}
- (void)viewWillDisappear:(BOOL)animated {
_mapView.delegate = nil;
}
- (void)dealloc{
if (_mapView) {
_mapView = nil;
}
}
备注:如果没有调用dealloc方法,请查看问题4的解决方法
解决问题2.网络请求,页面返回的时候没有终止网络加载任务
根据简书上的文章iOS取消界面的网络请求得到的答案:要取消网络请求,就需要一个类NSURLSessionDataTask的对象方法-cancel,有时候一个页面可能有多个请求,这个时候怎么办呢?对,可以将每个task放在数组里,然后在页面退出调用dealloc方法时,遍历一下这个数组,判断如果有正在执行中的任务取消掉就可以了。就是这么简单!
// 将请求任务添加到数组中,以post方式为例,get方式相同
NSURLSessionDataTask *urlTask = [self.httpSessionManager POST:URLString parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
DebugLog(@"====请求成功获取到的数据====%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
DebugLog(@"error ==>%@",error);
}];
[self.urlTaskArray addObject:urlTask];
// 然后在这里遍历数组,取消掉正在执行的任务
- (void)dealloc{
if (self.urlTaskArray.count) {
for (NSURLSessionDataTask *urlTask in self.urlTaskArray) {
if (urlTask.state == NSURLSessionTaskStateRunning) {
[urlTask cancel];
}
}
}
}
解决问题3.加载的h5页面,没有进行缓存,着实体验不佳,每次都要加载
思路是第一次加载之后进行缓存,下次直接从缓存中获取,不用再次加载,详见我的另一篇文章
iOS 缓存之(WebView)网页缓存
解决问题4.dealloc方法,为什么没有执行?
根本原因是当前的控制器的引用计数不为1,就是说可能存在没有被释放的情况,造成了循环引用。
可能有这几种情况:
1>代理属性是否使用assign进行修饰,而不是weak,assign比weak少了一个功能,对象不用时不能自动设置成nil。
2>block中是否使self,而不是__weak typeof(self) weakSelf = self; 中的weakSelf,造成了相互持有,都不能释放掉。
3>遵守的协议有没有设置能nil。
- (void)viewWillAppear:(BOOL)animated {
_mapView.delegate = self;
}
- (void)viewWillDisappear:(BOOL)animated {
_mapView.delegate = nil;
}
经过鄙人的测试,一般就是这几个问题造成的,如果还是没有执行dealloc方法,请反复进行核实以上步骤。
解决5.app中怎样减少loading,达到更顺畅的体验
情形1>app中有两个详情页面需要先加载图片,然后在显示其他内容,而且图片也是要加载原图,因为图片质量较高,所以添加了loading,是的使用了SDWebImage进行缓存,但是每次都显示loading体验不太好。解决方法,每次显示loaidng前,先进行判断如果有缓存,将不显示loading直接从缓存中取得图片。获取SDWebImage缓存的方法
// 因为这个方法在子线程(全局队列)中执行,所以不需要考虑死线程的问题
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager diskImageExistsForURL:pathUrl]; // pathUrl 是你要加载图片的url
if ([manager diskImageExistsForURL:pathUrl]) {
UIImage *image = [[manager imageCache] imageFromDiskCacheForKey:pathUrl.absoluteString];
[self loadSquarePhotoWithImage:image];
}else{
[SVProgressHUD show];
UIImageView *tappedImageView = [[UIImageView alloc]init];
__weak typeof(self) weakSelf = self;
[tappedImageView sd_setImageWithURL:pathUrl placeholderImage:nil options:SDWebImageProgressiveDownload completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
tappedImageView.image = image;
[weakSelf loadSquarePhotoWithImage:image];
[SVProgressHUD dismiss];
}];
}
情形2>每次加载h5的时候,考虑到网络情况不稳定,网速慢的情况,添加了loading,但是每次打开都要显示loading,都要加载一次,体验不好。
思路是第一次加载显示loading,加载完成之后进行缓存,下次直接从缓存中获取,不用再次加载,也不用在显示loading了,详见我的另一篇文章
iOS 缓存之(WebView)网页缓存
网友评论