美文网首页
iOS 简谈优化(一)

iOS 简谈优化(一)

作者: silence_xz | 来源:发表于2017-04-13 23:30 被阅读116次

    最近发现应用有卡顿现象,后来仔细查找,发现有几个地方是挺耗内存的。

    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)网页缓存

    相关文章

      网友评论

          本文标题:iOS 简谈优化(一)

          本文链接:https://www.haomeiwen.com/subject/egdvattx.html